Skip to main content
Every agent needs an orchagent.json file that defines its configuration, dependencies, and runtime limits.
Skills use a different format. Skills use a SKILL.md file with YAML frontmatter instead of orchagent.json. See Agent Types for the SKILL.md format.

Basic Structure

{
  "name": "my-agent",
  "type": "prompt",
  "description": "What my agent does",
  "supported_providers": ["openai", "anthropic"],
  "default_endpoint": "analyze",
  "timeout_seconds": 60
}
Versions are auto-assigned. You don’t need to specify a version field in your manifest. The server automatically assigns versions on each publish (v1, v2, v3…).

Required Fields

FieldTypeDescription
namestringAgent name (lowercase, hyphens allowed)
typestring"prompt" (default), "tool", "agent", or "skill". Legacy values code and agentic are accepted.
descriptionstringShort description of what the agent does
supported_providersarrayLLM providers: ["openai", "anthropic", "gemini", "any"]. agent types (managed loop) must use ["anthropic"].

Behavior Fields

These fields control how and when the agent runs. The type field sets the default execution engine, but these declarations can override it.
FieldTypeDefaultDescription
run_modestring"on_demand""on_demand" or "always_on". Always-on agents can be deployed as services.
runtimeobjectDeclares code execution. Sets execution_engine to code_runtime.
loopobjectDeclares managed LLM loop. Sets execution_engine to managed_loop.
callablebooleantrueWhether other agents can call this agent as a dependency. Set to false for user-facing agents that shouldn’t be invoked by orchestrators (e.g., always-on services).
runtime and loop are mutually exclusive — you cannot declare both. The type field sets the default execution engine: promptdirect_llm, toolcode_runtime, agentmanaged_loop. These declarations override the type default when present.

runtime

Declares that the agent runs custom code:
{
  "runtime": {
    "command": "python main.py"
  }
}
FieldTypeDescription
runtime.commandstringShell command to execute in the sandbox

loop

Declares that the agent uses a managed LLM tool-use loop:
{
  "loop": {
    "max_turns": 25
  }
}
FieldTypeDefaultDescription
loop.max_turnsnumber25Maximum loop iterations (platform max: 50)

Optional Fields

FieldTypeDefaultDescription
default_endpointstring"run"Default endpoint for orch run
timeout_secondsnumber300Request timeout (seconds)
tagsarray[]Searchable tags
is_publicbooleanfalseAll agents are private by default
default_modelsobject{}Per-provider model defaults. See Default Models below.
default_skillsarray[]Skills to inject into agent prompts (e.g., ["yourorg/writing-style"])
skills_lockedbooleanfalseWhen true, callers cannot override default_skills via flags (immutable after publish)
required_secretsarray[]Env var names your agent needs at runtime. See Workspace Secrets below. Required for tool and agent types.
optional_secretsarray[]Env var names that unlock additional features but aren’t required. Shown in orch info for discoverability.

Default Models

Control which LLM model runs your agent by default for each provider. The default_models field is an object mapping provider names to model IDs:
{
  "name": "my-agent",
  "type": "prompt",
  "supported_providers": ["anthropic", "openai", "gemini"],
  "default_models": {
    "anthropic": "claude-sonnet-4-20250514",
    "openai": "gpt-4o",
    "gemini": "gemini-2.5-pro"
  }
}

Model Resolution Order

When your agent runs, the model is resolved in this order:
  1. Caller overrideorch run --model <model> (highest priority)
  2. Agent defaultdefault_models[provider] from your manifest
  3. Platform default — built-in defaults per provider
ProviderPlatform Default
anthropicclaude-opus-4-5-20251101
openaigpt-5.2
geminigemini-2.5-pro
ollamallama3.2
Use default_models (plural object), not model (singular string). A common mistake is writing "model": "claude-sonnet-4-20250514" — this field is ignored. The correct format is "default_models": { "anthropic": "claude-sonnet-4-20250514" }.
Set default_models to control costs. For example, use a smaller model like claude-haiku-4-5-20251001 for simple tasks, and let callers override with --model when they need a more capable model.
orch publish and orch validate will warn if your model IDs don’t match known provider patterns (e.g. gpt-* for OpenAI, claude-* for Anthropic, gemini-* for Gemini). This catches typos and mismatches before they cause 404 errors at runtime.

Workspace Secrets

Declare the environment variables your agent needs at runtime using required_secrets, and variables that unlock additional features using optional_secrets. Both are matched by name against your workspace secrets vault and injected as env vars into the sandbox.
{
  "name": "cto-agent",
  "type": "agent",
  "required_secrets": ["MONITOR_URLS", "ANTHROPIC_API_KEY"],
  "optional_secrets": ["DISCORD_WEBHOOK_URL", "SLACK_WEBHOOK_URL", "BACKUP_S3_ENDPOINT"]
}
At runtime, your code reads them as environment variables:
import os
token = os.environ["ANTHROPIC_API_KEY"]
webhook = os.environ.get("DISCORD_WEBHOOK_URL")  # optional — may not be set

How it works

  1. You declare required_secrets and optional_secrets in orchagent.json
  2. You add secrets to your workspace vault (dashboard or orch secrets set)
  3. At runtime, the platform matches secret names and injects them as env vars
  4. On-demand runs (orch run): returns a 400 MISSING_SECRETS error if any required secrets are missing from the vault. Optional secrets are injected if present, silently skipped if not.
  5. Service deploys (orch service deploy): auto-reads required_secrets and validates against the vault before deploying. No --secret flags needed.
  6. Schedules: same injection — required secrets must exist in the vault at execution time
  7. orch info: shows both required and optional secrets so users can discover all available configuration

Optional secrets

Use optional_secrets to declare env vars that aren’t needed to run but unlock additional features — notification webhooks, backup integrations, model overrides, tuning parameters, etc. Without this field, users have no way to discover these options except by reading the README.
$ orch info orchagent/cto-agent-template
Secrets (required): MONITOR_URLS, ANTHROPIC_API_KEY
Secrets (optional): DISCORD_WEBHOOK_URL, SLACK_WEBHOOK_URL, BACKUP_S3_ENDPOINT, ...

Publish enforcement

orch publish blocks tool and agent types that don’t declare required_secrets. This ensures the Agent Requirements UI and service auto-resolution always have accurate data. Use --no-required-secrets to bypass this check if your agent genuinely needs no secrets. Prompt and skill types are exempt. optional_secrets is never enforced — it’s purely informational.
Do not add ORCHAGENT_SERVICE_KEY to required_secrets. The gateway auto-injects a temporary service key for agents with manifest dependencies. Adding your own overrides it and breaks orchestration.

Tool Type Fields

Additional fields for tool types (code runtime — runtime.command):
FieldTypeDescription
entrypointstringEntry file to execute (e.g., sandbox_main.py)
source_urlstringGit URL for local execution
run_commandstringCommand to run locally
bundleobjectBundle configuration (see below)

Bundle Configuration

Control what files are included in your code bundle:
{
  "bundle": {
    "exclude": ["data/", "*.log", "large_model.bin"],
    "include": ["important.dat"]
  }
}
FieldTypeDescription
excludearrayGlob patterns to exclude from bundle
includearrayGlob patterns to include (overrides excludes)

Example

{
  "name": "leak-finder",
  "type": "tool",
  "description": "Finds leaked secrets in codebases",
  "supported_providers": ["gemini"],
  "runtime": {
    "command": "python sandbox_main.py"
  },
  "required_secrets": ["GEMINI_API_KEY"],
  "entrypoint": "sandbox_main.py",
  "tags": ["security", "scanning"],
  "is_public": true
}
For E2B sandbox execution (recommended), only runtime.command (or entrypoint) is needed. The source_url and run_command fields are for local execution support.

Prompt Type Fields

Additional fields for prompt types (direct LLM — no runtime or loop):
FieldTypeDescription
prompt_templatestringPrompt with {{variable}} placeholders
input_schemaobjectJSON Schema for input validation
output_schemaobjectJSON Schema for output validation

Example

{
  "name": "summarizer",
  "type": "prompt",
  "description": "Summarizes text content",
  "supported_providers": ["openai", "anthropic"],
  "prompt_template": "Summarize the following text in {{style}} style:\n\n{{text}}",
  "input_schema": {
    "type": "object",
    "properties": {
      "text": { "type": "string" },
      "style": { "type": "string", "enum": ["bullet", "paragraph", "tldr"] }
    },
    "required": ["text", "style"]
  },
  "output_schema": {
    "type": "object",
    "properties": {
      "summary": { "type": "string" }
    },
    "required": ["summary"]
  }
}

Agent Type Fields

Additional fields for agent types (managed loop):
FieldTypeDefaultDescription
custom_toolsarray[]Command-wrapper tools available to the LLM
timeout_secondsnumber300Overall execution timeout

Custom Tools Format

Each custom tool has:
FieldRequiredDescription
nameYesTool name the LLM will call
descriptionYesWhat the tool does (shown to LLM)
commandYesShell command to execute. Use {{param}} for parameters.
input_schemaNoJSON Schema for parameters (required if command has {{param}} placeholders)

Example

{
  "name": "cairo-test-engineer",
  "type": "agent",
  "description": "Fixes Cairo code until tests pass",
  "supported_providers": ["anthropic"],
  "loop": {
    "max_turns": 30
  },
  "timeout_seconds": 300,
  "custom_tools": [
    {
      "name": "run_tests",
      "description": "Run the Cairo test suite",
      "command": "snforge test"
    },
    {
      "name": "deploy",
      "description": "Deploy to the specified network",
      "command": "sncast deploy --network {{network}}",
      "input_schema": {
        "type": "object",
        "properties": {
          "network": { "type": "string", "description": "Target network" }
        },
        "required": ["network"]
      }
    }
  ]
}
Agent types also get built-in tools automatically: bash, read_file, write_file, list_files, and submit_result. You don’t need to define these. See Agent Types for details.
If your agent declares manifest.dependencies, you must also define matching custom_tools. Without custom_tools, the LLM has no way to invoke dependencies — it will waste turns exploring the sandbox filesystem instead. Use orch scaffold orchestration to auto-generate custom_tools from your dependency list. This only applies to managed-loop agents; code_runtime agents call dependencies via the SDK directly.

Skill Composition

Agents can include skills by default using the default_skills field. Skills are injected into the agent’s prompt at runtime.
{
  "name": "code-reviewer",
  "type": "prompt",
  "description": "Reviews code with best practices",
  "supported_providers": ["anthropic", "openai"],
  "default_skills": [
    "yourorg/react-best-practices",
    "yourorg/writing-style"
  ],
  "prompt_template": "Review this code:\n\n{{code}}"
}
When called, the agent’s prompt is prepended with the content from each skill. Callers can override this behavior (unless skills are locked):
  • --skills org/skill - Add more skills
  • --skills-only org/skill - Replace default_skills entirely
  • --no-skills - Ignore all skills

Locking Skills

Add skills_locked: true to prevent callers from overriding your default skills:
{
  "name": "secure-reviewer",
  "default_skills": ["yourorg/owasp-rules"],
  "skills_locked": true
}
See Orchestration - Locking Skills for details.

Manifest Section (for Orchestrator Agents)

Agents that call other agents need a manifest section:
{
  "name": "security-review",
  "type": "tool",
  "description": "Comprehensive security review",
  "runtime": {
    "command": "python main.py"
  },
  "manifest": {
    "manifest_version": 1,
    "dependencies": [
      { "id": "joe/leak-finder", "version": "v1" },
      { "id": "joe/vuln-scanner", "version": "v1" }
    ],
    "max_hops": 2,
    "timeout_ms": 120000,
    "per_call_downstream_cap": 100
  }
}

Manifest Fields

FieldRequiredDescription
manifest_versionYesAlways 1
dependenciesYesArray of {id, version} for agents you’ll call
max_hopsYesMax call depth (>= 1 if you have deps)
timeout_msYesTotal timeout for your agent
per_call_downstream_capNoBudget passed to each dependency call (default: 50). Limits child agent spending, not this agent’s own calls.
orchestration_modeNo"strict" or "flexible". Controls whether the agent must use dependency-path execution. See Orchestration Mode below. Defaults to "strict" when dependencies are declared.
min_required_hopsNoMinimum hops caller must allow
regionNoDeployment region
visibilityNopublic or private
recommended_min_caller_budgetNoSuggested minimum budget for callers

Dependency Format

{
  "id": "org_slug/agent_name",
  "version": "v1"
}

Orchestration Mode

Controls whether a managed-loop orchestrator must delegate to its declared dependencies or can solve tasks directly with built-in tools like bash.
{
  "manifest": {
    "manifest_version": 1,
    "dependencies": [{ "id": "yourorg/scanner", "version": "v1" }],
    "orchestration_mode": "strict"
  }
}
ValueBehavior
"strict"bash is removed from available tools. The agent must call at least one dependency before submitting results. This is the default when dependencies are declared.
"flexible"All built-in tools (including bash) remain available. The agent can solve tasks directly or via dependencies.
Rules:
  • Only applies to managed-loop agents (type: "agent" or loop declared) with dependencies.
  • If dependencies is empty or absent, the field is ignored.
  • Orchestrators with dependencies default to "strict" unless you explicitly set "flexible".
  • In multi-agent chains, strict mode is inherited downward — a strict parent forces all downstream agents to run strict, regardless of their own setting.
To use flexible mode instead:
{
  "manifest": {
    "orchestration_mode": "flexible",
    "dependencies": [{ "id": "yourorg/scanner", "version": "v1" }]
  }
}
See Orchestration - Strict vs Flexible Mode for details on behavior, error codes, and chain inheritance.

Validation Rules

The platform validates manifests on publish:
  1. Dependencies exist - All declared dependencies must be registered
  2. No cycles - Dependency graph must be acyclic
  3. max_hops >= 1 - Required when dependencies are declared
  4. Version pins - Dependencies must specify exact versions
  5. No conflicts - runtime and loop cannot both be declared
  6. Run mode compatibility - always_on requires runtime.command or loop (cannot be used with direct_llm)

Complete Examples

Always-On Tool Type

{
  "name": "discord-bot",
  "type": "tool",
  "description": "Discord moderation bot",
  "supported_providers": ["any"],
  "run_mode": "always_on",
  "runtime": {
    "command": "python bot.py"
  },
  "required_secrets": ["DISCORD_BOT_TOKEN", "ANTHROPIC_API_KEY"],
  "callable": false,
  "timeout_seconds": 0,
  "tags": ["discord", "moderation"]
}

On-Demand Agent Type (Managed Loop)

{
  "name": "code-fixer",
  "type": "agent",
  "description": "Fixes code until tests pass",
  "supported_providers": ["anthropic"],
  "run_mode": "on_demand",
  "loop": {
    "max_turns": 30
  },
  "required_secrets": ["ANTHROPIC_API_KEY"],
  "timeout_seconds": 300,
  "custom_tools": [
    {
      "name": "run_tests",
      "description": "Run the test suite",
      "command": "pytest"
    }
  ]
}

On-Demand Prompt Type (Direct LLM)

{
  "name": "summarizer",
  "type": "prompt",
  "description": "Summarizes documents",
  "supported_providers": ["openai", "anthropic", "gemini"],
  "run_mode": "on_demand",
  "callable": false
}

Orchestrator (Tool Type)

{
  "name": "security-review",
  "type": "tool",
  "description": "Comprehensive security review combining multiple scanners",
  "supported_providers": ["any"],
  "runtime": {
    "command": "python main.py"
  },
  "timeout_seconds": 180,
  "tags": ["security", "scanning", "orchestrator"],
  "manifest": {
    "manifest_version": 1,
    "dependencies": [
      { "id": "joe/leak-finder", "version": "v1" },
      { "id": "joe/vuln-scanner", "version": "v1" },
      { "id": "joe/license-checker", "version": "v1" }
    ],
    "max_hops": 2,
    "timeout_ms": 180000,
    "per_call_downstream_cap": 50,
    "min_required_hops": 2,
    "region": "us-east",
    "visibility": "public"
  }
}