> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orchagent.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Manifest Format

> The orchagent.json configuration schema

Every agent needs an `orchagent.json` file that defines its configuration, dependencies, and runtime limits.

<Note>
  **Skills use a different format.** Skills use a `SKILL.md` file with YAML frontmatter instead of `orchagent.json`. See [Agent Types](/building-agents/agent-types#skill-type-type-skill) for the SKILL.md format.
</Note>

## Basic Structure

```json theme={null}
{
  "name": "my-agent",
  "type": "prompt",
  "description": "What my agent does",
  "supported_providers": ["openai", "anthropic"],
  "default_endpoint": "analyze",
  "timeout_seconds": 60
}
```

<Note>
  **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...).
</Note>

## Required Fields

| Field                 | Type   | Description                                                                                                       |
| --------------------- | ------ | ----------------------------------------------------------------------------------------------------------------- |
| `name`                | string | Agent name (lowercase, hyphens allowed)                                                                           |
| `type`                | string | `"prompt"` (default), `"tool"`, `"agent"`, or `"skill"`. Legacy values `code` and `agentic` are accepted.         |
| `description`         | string | Short description of what the agent does                                                                          |
| `supported_providers` | array  | LLM 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.

| Field      | Type    | Default       | Description                                                                                                                                                            |
| ---------- | ------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `run_mode` | string  | `"on_demand"` | `"on_demand"` or `"always_on"`. Always-on agents can be deployed as [services](/using-agents/services).                                                                |
| `runtime`  | object  | —             | Declares code execution. Sets `execution_engine` to `code_runtime`.                                                                                                    |
| `loop`     | object  | —             | Declares managed LLM loop. Sets `execution_engine` to `managed_loop`.                                                                                                  |
| `callable` | boolean | `true`        | Whether 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). |

<Warning>
  `runtime` and `loop` are mutually exclusive — you cannot declare both. The `type` field sets the default execution engine: `prompt` → `direct_llm`, `tool` → `code_runtime`, `agent` → `managed_loop`. These declarations override the type default when present.
</Warning>

### runtime

Declares that the agent runs custom code:

```json theme={null}
{
  "runtime": {
    "command": "python main.py"
  }
}
```

| Field             | Type   | Description                             |
| ----------------- | ------ | --------------------------------------- |
| `runtime.command` | string | Shell command to execute in the sandbox |

### loop

Declares that the agent uses a managed LLM tool-use loop:

```json theme={null}
{
  "loop": {
    "max_turns": 25
  }
}
```

| Field            | Type   | Default | Description                                |
| ---------------- | ------ | ------- | ------------------------------------------ |
| `loop.max_turns` | number | `25`    | Maximum loop iterations (platform max: 50) |

## Optional Fields

| Field              | Type    | Default | Description                                                                                                                              |
| ------------------ | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `default_endpoint` | string  | `"run"` | Default endpoint for `orch run`                                                                                                          |
| `timeout_seconds`  | number  | `300`   | Request timeout (seconds)                                                                                                                |
| `tags`             | array   | `[]`    | Searchable tags                                                                                                                          |
| `is_public`        | boolean | `false` | All agents are private by default                                                                                                        |
| `default_models`   | object  | `{}`    | Per-provider model defaults. See [Default Models](#default-models) below.                                                                |
| `default_skills`   | array   | `[]`    | Skills to inject into agent prompts (e.g., `["yourorg/writing-style"]`)                                                                  |
| `skills_locked`    | boolean | `false` | When true, callers cannot override default\_skills via flags (immutable after publish)                                                   |
| `required_secrets` | array   | `[]`    | Env var names your agent needs at runtime. See [Workspace Secrets](#workspace-secrets) below. **Required for `tool` and `agent` types.** |
| `optional_secrets` | array   | `[]`    | 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:

```json theme={null}
{
  "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 override** — `orch run --model <model>` (highest priority)
2. **Agent default** — `default_models[provider]` from your manifest
3. **Platform default** — built-in defaults per provider

| Provider    | Platform Default           |
| ----------- | -------------------------- |
| `anthropic` | `claude-opus-4-5-20251101` |
| `openai`    | `gpt-5.2`                  |
| `gemini`    | `gemini-2.5-pro`           |
| `ollama`    | `llama3.2`                 |

<Warning>
  **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" }`.
</Warning>

<Tip>
  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.
</Tip>

<Note>
  `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.
</Note>

## 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.

```json theme={null}
{
  "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:

```python theme={null}
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.

<Warning>
  **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.
</Warning>

## Tool Type Fields

Additional fields for `tool` types (code runtime — `runtime.command`):

| Field         | Type   | Description                                     |
| ------------- | ------ | ----------------------------------------------- |
| `entrypoint`  | string | Entry file to execute (e.g., `sandbox_main.py`) |
| `source_url`  | string | Git URL for local execution                     |
| `run_command` | string | Command to run locally                          |
| `bundle`      | object | Bundle configuration (see below)                |

### Bundle Configuration

Control what files are included in your code bundle:

```json theme={null}
{
  "bundle": {
    "exclude": ["data/", "*.log", "large_model.bin"],
    "include": ["important.dat"]
  }
}
```

| Field     | Type  | Description                                   |
| --------- | ----- | --------------------------------------------- |
| `exclude` | array | Glob patterns to exclude from bundle          |
| `include` | array | Glob patterns to include (overrides excludes) |

### Example

```json theme={null}
{
  "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
}
```

<Note>
  For E2B sandbox execution (recommended), only `runtime.command` (or `entrypoint`) is needed. The `source_url` and `run_command` fields are for local execution support.
</Note>

## Prompt Type Fields

Additional fields for `prompt` types (direct LLM — no `runtime` or `loop`):

| Field             | Type   | Description                             |
| ----------------- | ------ | --------------------------------------- |
| `prompt_template` | string | Prompt with `{{variable}}` placeholders |
| `input_schema`    | object | JSON Schema for input validation        |
| `output_schema`   | object | JSON Schema for output validation       |

### Example

```json theme={null}
{
  "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):

| Field             | Type   | Default | Description                                |
| ----------------- | ------ | ------- | ------------------------------------------ |
| `custom_tools`    | array  | `[]`    | Command-wrapper tools available to the LLM |
| `timeout_seconds` | number | `300`   | Overall execution timeout                  |

### Custom Tools Format

Each custom tool has:

| Field          | Required | Description                                                                   |
| -------------- | -------- | ----------------------------------------------------------------------------- |
| `name`         | Yes      | Tool name the LLM will call                                                   |
| `description`  | Yes      | What the tool does (shown to LLM)                                             |
| `command`      | Yes      | Shell command to execute. Use `{{param}}` for parameters.                     |
| `input_schema` | No       | JSON Schema for parameters (required if command has `{{param}}` placeholders) |

### Example

```json theme={null}
{
  "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"]
      }
    }
  ]
}
```

<Note>
  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](/building-agents/agent-types#built-in-tools) for details.
</Note>

<Warning>
  **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.
</Warning>

## Skill Composition

Agents can include skills by default using the `default_skills` field. Skills are injected into the agent's prompt at runtime.

```json theme={null}
{
  "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:

```json theme={null}
{
  "name": "secure-reviewer",
  "default_skills": ["yourorg/owasp-rules"],
  "skills_locked": true
}
```

See [Orchestration - Locking Skills](/building-agents/orchestration#locking-skills) for details.

## Manifest Section (for Orchestrator Agents)

Agents that call other agents need a `manifest` section:

```json theme={null}
{
  "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

| Field                           | Required | Description                                                                                                                                                                                            |
| ------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `manifest_version`              | Yes      | Always `1`                                                                                                                                                                                             |
| `dependencies`                  | Yes      | Array of `{id, version}` for agents you'll call                                                                                                                                                        |
| `max_hops`                      | Yes      | Max call depth (>= 1 if you have deps)                                                                                                                                                                 |
| `timeout_ms`                    | Yes      | Total timeout for your agent                                                                                                                                                                           |
| `per_call_downstream_cap`       | No       | Budget passed to each dependency call (default: `50`). Limits child agent spending, not this agent's own calls.                                                                                        |
| `orchestration_mode`            | No       | `"strict"` or `"flexible"`. Controls whether the agent must use dependency-path execution. See [Orchestration Mode](#orchestration-mode) below. Defaults to `"strict"` when dependencies are declared. |
| `min_required_hops`             | No       | Minimum hops caller must allow                                                                                                                                                                         |
| `region`                        | No       | Deployment region                                                                                                                                                                                      |
| `visibility`                    | No       | `public` or `private`                                                                                                                                                                                  |
| `recommended_min_caller_budget` | No       | Suggested minimum budget for callers                                                                                                                                                                   |

### Dependency Format

```json theme={null}
{
  "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`.

```json theme={null}
{
  "manifest": {
    "manifest_version": 1,
    "dependencies": [{ "id": "yourorg/scanner", "version": "v1" }],
    "orchestration_mode": "strict"
  }
}
```

| Value        | Behavior                                                                                                                                                               |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"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:

```json theme={null}
{
  "manifest": {
    "orchestration_mode": "flexible",
    "dependencies": [{ "id": "yourorg/scanner", "version": "v1" }]
  }
}
```

See [Orchestration - Strict vs Flexible Mode](/building-agents/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

```json theme={null}
{
  "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)

```json theme={null}
{
  "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)

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

### Orchestrator (Tool Type)

```json theme={null}
{
  "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"
  }
}
```
