Skip to main content

Agent Config Export & Import

Round-trip agent configurations between environments with secret redaction, schema validation, and CLI support.


Table of Contents

  1. Overview
  2. Quick Start
  3. CLI Commands
  4. Programmatic API
  5. Export Formats
  6. Secret Redaction
  7. Schema Validation
  8. Round-Trip Workflow
  9. Portable Agent Bundles
  10. Examples
  11. Related Documentation

Overview

Agent configurations contain everything needed to reproduce an agent: personality, security tier, LLM provider settings, skills, channels, extensions, and tool permissions. The export/import system lets you:

  • Share agent configurations between team members
  • Version agent configs in Git alongside application code
  • Migrate agents between environments (dev/staging/prod)
  • Backup and restore agent state
  • Template new agents from proven configurations

Secrets (API keys, tokens) are automatically redacted on export and must be re-supplied on import.


Quick Start

Export an Agent

# Export to YAML (default)
wunderland export --output my-agent.yaml

# Export to JSON
wunderland export --format json --output my-agent.json

# Export from a specific config directory
wunderland export --config ~/.wunderland/agents/research-bot --output research-bot.yaml

Import an Agent

# Import from file
wunderland import my-agent.yaml

# Import to a specific directory
wunderland import my-agent.yaml --target ~/.wunderland/agents/new-agent

# Import with automatic secret prompting
wunderland import my-agent.yaml --prompt-secrets

CLI Commands

wunderland export

Export the current agent configuration to a portable file.

Usage: wunderland export [options]

Options:
--output, -o <path> Output file path (default: stdout)
--format <yaml|json> Output format (default: yaml)
--config <path> Config directory to export from
--include-skills Include resolved skill content (default: false)
--include-workflows Include workflow definitions (default: false)
--no-redact Skip secret redaction (DANGEROUS — includes raw API keys)
--pretty Pretty-print JSON output (default: true)

wunderland import

Import an agent configuration from a file.

Usage: wunderland import <file> [options]

Options:
--target <path> Target config directory (default: current)
--prompt-secrets Interactively prompt for redacted secrets
--merge Merge with existing config instead of replacing
--dry-run Show what would change without writing
--validate-only Validate the file without importing
--yes, -y Skip confirmation prompts

Programmatic API

exportAgentConfig()

import { exportAgentConfig } from '@framers/agentos';

const exported = await exportAgentConfig({
configDir: '~/.wunderland', // Config directory to read
format: 'yaml', // 'yaml' | 'json'
includeSkills: false, // Include resolved SKILL.md content
includeWorkflows: false, // Include workflow definitions
redactSecrets: true, // Replace secrets with placeholders
});

console.log(exported.content); // YAML/JSON string
console.log(exported.format); // 'yaml'
console.log(exported.redactedKeys); // ['OPENAI_API_KEY', 'ANTHROPIC_API_KEY', ...]
console.log(exported.warnings); // Any validation warnings

importAgent()

import { importAgent } from '@framers/agentos';

const result = await importAgent({
source: './my-agent.yaml', // File path or string content
targetDir: '~/.wunderland', // Where to write the config
merge: false, // Replace (false) or merge (true)
secrets: { // Supply redacted secrets
OPENAI_API_KEY: 'sk-...',
ANTHROPIC_API_KEY: 'sk-ant-...',
},
});

console.log(result.configDir); // Resolved target directory
console.log(result.changes); // List of files written
console.log(result.warnings); // Any import warnings

agent.export() / agent.exportJSON()

Export from an instantiated agent:

import { createAgent } from '@framers/agentos';

const agent = await createAgent({ /* ... */ });

// Export as YAML string
const yaml = await agent.export();

// Export as parsed JSON object
const json = await agent.exportJSON();
console.log(json.personality); // { hexaco: { ... } }
console.log(json.llmProvider); // "openai"
console.log(json.skills); // ["research-assistant", "web-search"]

Export Formats

YAML Format (Default)

# AgentOS Agent Configuration Export
# Exported: 2026-03-26T12:00:00Z
# Version: 1.0.0

meta:
exportVersion: "1.0.0"
agentosVersion: "0.48.0"
exportedAt: "2026-03-26T12:00:00Z"

agent:
name: "Research Assistant"
description: "A research-focused agent with web search and deep analysis"

personality:
hexaco:
honestyHumility: 0.85
emotionality: 0.40
extraversion: 0.60
agreeableness: 0.75
conscientiousness: 0.90
opennessToExperience: 0.95

llm:
provider: "anthropic"
model: "claude-sonnet-4-20250514"
fallback:
- "openrouter"

security:
tier: "balanced"
executionMode: "deny-side-effects"
approvedTools:
- "web-search"
- "web-browser"
- "news-search"

skills:
- "research-assistant"
- "deep-research"
- "web-search"

channels:
- platform: "webchat"
enabled: true
- platform: "slack"
enabled: true

extensions:
- "web-search"
- "web-browser"
- "news-search"

memory:
type: "cognitive"
ragEnabled: true
vectorStore: "hnsw"

secrets:
ANTHROPIC_API_KEY: "<<REDACTED>>"
OPENROUTER_API_KEY: "<<REDACTED>>"
DEEPGRAM_API_KEY: "<<REDACTED>>"

JSON Format

{
"meta": {
"exportVersion": "1.0.0",
"agentosVersion": "0.48.0",
"exportedAt": "2026-03-26T12:00:00Z"
},
"agent": {
"name": "Research Assistant",
"description": "A research-focused agent with web search and deep analysis"
},
"personality": {
"hexaco": {
"honestyHumility": 0.85,
"emotionality": 0.40,
"extraversion": 0.60,
"agreeableness": 0.75,
"conscientiousness": 0.90,
"opennessToExperience": 0.95
}
},
"llm": {
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"fallback": ["openrouter"]
},
"security": {
"tier": "balanced",
"executionMode": "deny-side-effects",
"approvedTools": ["web-search", "web-browser", "news-search"]
},
"skills": ["research-assistant", "deep-research", "web-search"],
"channels": [
{ "platform": "webchat", "enabled": true },
{ "platform": "slack", "enabled": true }
],
"extensions": ["web-search", "web-browser", "news-search"],
"memory": {
"type": "cognitive",
"ragEnabled": true,
"vectorStore": "hnsw"
},
"secrets": {
"ANTHROPIC_API_KEY": "<<REDACTED>>",
"OPENROUTER_API_KEY": "<<REDACTED>>",
"DEEPGRAM_API_KEY": "<<REDACTED>>"
}
}

Secret Redaction

By default, all known secret patterns are replaced with <<REDACTED>> on export. The list of redacted keys includes:

PatternExamples
*_API_KEYOPENAI_API_KEY, ANTHROPIC_API_KEY, STABILITY_API_KEY
*_API_TOKENREPLICATE_API_TOKEN, TELEGRAM_BOT_TOKEN
*_SECRETSLACK_OAUTH_CLIENT_SECRET, WUNDERLAND_INTERNAL_API_SECRET
*_AUTH_TOKENTWILIO_AUTH_TOKEN, WUNDERLAND_AUTH_TOKEN
*_PASSWORDDatabase passwords, SMTP passwords
*_PRIVATE_KEYSolana private keys, SSH keys

Exporting Without Redaction

Use --no-redact for trusted environments (e.g., encrypted backup):

# WARNING: Output will contain raw API keys
wunderland export --no-redact --output backup.yaml

Supplying Secrets on Import

# Interactive prompting for each redacted secret
wunderland import my-agent.yaml --prompt-secrets

# Supply secrets via environment variables (they're matched by name)
OPENAI_API_KEY=sk-... wunderland import my-agent.yaml

# Supply secrets programmatically
await importAgent({
source: './my-agent.yaml',
secrets: {
OPENAI_API_KEY: process.env.OPENAI_API_KEY!,
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,
},
});

Schema Validation

Exported configurations are validated against a JSON Schema on both export and import:

# Validate without importing
wunderland import my-agent.yaml --validate-only

# Output:
# ✓ Schema version: 1.0.0
# ✓ Required fields: present
# ✓ LLM provider: valid (anthropic)
# ✓ Security tier: valid (balanced)
# ✓ Skills: 3 referenced, all resolvable
# ⚠ Secrets: 3 redacted keys (supply on import)

Programmatic Validation

import { validateAgentConfig } from '@framers/agentos';

const result = validateAgentConfig('./my-agent.yaml');

if (result.valid) {
console.log('Config is valid');
} else {
for (const error of result.errors) {
console.error(`${error.path}: ${error.message}`);
}
}

Round-Trip Workflow

A typical workflow for migrating an agent between environments:

# 1. Export from development
cd ~/dev-agent
wunderland export --output agent-config.yaml

# 2. Commit to version control
git add agent-config.yaml
git commit -m "Export research-assistant config"

# 3. Import on production server
ssh prod-server
git pull
wunderland import agent-config.yaml --prompt-secrets --target /opt/agents/research-bot

# 4. Verify
wunderland doctor --config /opt/agents/research-bot

Team Sharing

# Developer A: Export and share
wunderland export --output team-agent.yaml --include-skills
# Commit to shared repo

# Developer B: Import and customize
wunderland import team-agent.yaml --merge --prompt-secrets
# The --merge flag preserves local settings while applying shared ones

Portable Agent Bundles

For sharing agents with all dependencies (skills, workflows, custom tools), use the bundle format:

# Create a self-contained bundle (.tar.gz)
wunderland export --bundle --output my-agent-bundle.tar.gz --include-skills --include-workflows

# The bundle contains:
# agent-config.yaml — Main configuration
# skills/ — Resolved SKILL.md files
# workflows/ — Workflow definitions
# tools/ — Custom tool definitions
# MANIFEST.json — Bundle metadata and checksums

Import a Bundle

wunderland import my-agent-bundle.tar.gz --target ~/.wunderland/agents/imported

Examples

Export for CI/CD

import { exportAgentConfig } from '@framers/agentos';
import { writeFileSync } from 'node:fs';

// Export without secrets for CI
const exported = await exportAgentConfig({
configDir: './agent-config',
format: 'json',
redactSecrets: true,
});

writeFileSync('./deploy/agent-config.json', exported.content);

// In CI, secrets come from environment
// OPENAI_API_KEY, ANTHROPIC_API_KEY, etc. are set as CI secrets

Clone an Agent

import { exportAgentConfig, importAgent } from '@framers/agentos';

// Export current agent
const exported = await exportAgentConfig({
configDir: '~/.wunderland/agents/original',
format: 'json',
redactSecrets: false, // Same machine, no need to redact
});

// Import as a new agent with modified settings
const config = JSON.parse(exported.content);
config.agent.name = 'Research Assistant v2';
config.llm.model = 'claude-opus-4-20250514';

await importAgent({
source: JSON.stringify(config),
targetDir: '~/.wunderland/agents/research-v2',
});

Diff Two Configs

# Export both configs and diff
wunderland export --config ./agent-a --format json --output /tmp/a.json
wunderland export --config ./agent-b --format json --output /tmp/b.json
diff /tmp/a.json /tmp/b.json