Pass-Through Config: How User Settings Reach Your Skill at Runtime
When a user configures your skill through the setup wizard, those values need to reach your code at runtime. This is pass-through config — the mechanism that takes user-provided settings, stores them securely, and delivers them to your skill every time it's invoked.
The Flow
User fills setup wizard
↓
Platform validates values (via your validation_command)
↓
Secrets → encrypted vault | Plain values → config.json
↓
User invokes your skill
↓
Agent resolves secrets from vault + merges config
↓
Your skill receives the full config in the request payload
What Your Skill Receives
Every invocation includes the user's config alongside the operation and payload:
{
"operation": "fetch_data",
"payload": {
"query": "latest reports"
},
"config": {
"api_key": "sk-live-abc123def456",
"workspace_id": "ws-789",
"max_results": 25,
"notify_on_error": true
}
}
Notice that api_key is the actual resolved value — not a vault reference. The agent handles decryption and resolution before your skill ever sees it. Your code just reads request.config.api_key and uses it.
How Secrets Are Handled
Fields marked with "x-secret": true in your config_schema get special treatment:
- Storage: The value is encrypted with AES-256-GCM and stored in the local vault — never in plaintext on disk.
- UI: Shown as
••••••••after initial entry. Users can update but never view the stored value. - Logging: Never appears in logs, error messages, or debug output.
- Resolution: At invocation time, the agent decrypts the value and passes it to your skill in the
configobject. - Sandbox: The secret is in the JSON payload on stdin — it's never set as an environment variable (which could leak via
/procon Linux).
Your skill doesn't need to know about the vault, encryption, or key management. You declare x-secret, and the platform handles the rest.
Config Override at Install Time
When a skill is installed from the marketplace, the platform can provide config overrides — default values or organization-wide settings that merge with the user's choices:
{
"config_override": {
"api_key_source": "vault",
"default_region": "us-east-1"
}
}
These overrides merge into the skill's config.json at install time. User-provided values (from the setup wizard) take precedence over overrides.
Updating Config After Install
Users can reconfigure your skill at any time through the platform UI. When they do:
- The setup wizard re-renders with current values (secrets shown as masked)
- User changes what they want
- Validation commands run again (if defined)
- New values are persisted
- Next invocation uses the updated config
Your skill doesn't need to handle config reloading — it gets the current config on every invocation. Stateless by design.
Accessing Config in Your Code
Node.js
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
rl.on('line', (line) => {
const request = JSON.parse(line);
const { operation, payload, config } = request;
// Use config values directly
const apiKey = config.api_key;
const maxResults = config.max_results || 10;
// Your logic here...
});
Python
import json
import sys
for line in sys.stdin:
request = json.loads(line.strip())
config = request.get("config", {})
api_key = config["api_key"]
max_results = config.get("max_results", 10)
# Your logic here...
Rust
#[derive(Deserialize)]
struct SkillRequest {
operation: String,
payload: serde_json::Value,
config: SkillConfig,
}
#[derive(Deserialize)]
struct SkillConfig {
api_key: String,
max_results: Option<u32>,
}
Best Practices
Don't cache config across invocations. Your skill is a short-lived process — read config from the request every time. This ensures you always have the latest values.
Validate config in your validation_command, not at runtime. By the time your skill is invoked, config should already be valid. The setup wizard catches errors early.
Use defaults in your schema. If a field has a sensible default, declare it. Users who don't customize still get working behavior.
Don't log secrets. Even though the agent redacts them from its own logs, your skill's stderr output might be captured. Never print config values that could be sensitive.
Handle missing optional fields gracefully. Not every field will be present — use defaults in your code for anything not in required.
The Security Model
The pass-through config system is designed so that:
- Secrets are encrypted at rest (vault)
- Secrets are decrypted only at invocation time (just-in-time resolution)
- Secrets are passed via stdin (not environment variables)
- The skill process is sandboxed (can't read other skills' configs)
- Config is scoped per-user, per-skill (no cross-contamination)
You get the convenience of "just read the config object" with the security of encrypted vault storage. No key management code in your skill, no credential files to protect, no rotation logic to implement.