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

# Build it with your coding agent

> Wire Claude Code, Codex or Cursor to Orca, then run the loop: describe the job, create the files, test on input built to break them, change one file, go again.

The [Start here](/start-here) guide has you write an agent by hand, which is the right way to meet the moving parts once. After that, the fastest way to build an Orca agent is to ask the coding agent you already have open. It knows your repo, it can read these docs, and with the CLI signed in it can create, run and fix the agent without you leaving the session.

Building one is a loop, not a checklist. You describe the job, your session writes two files, you create them, you run them against input chosen to break them, and then you change exactly one file and go again. Most agents take two or three turns around that loop. This page is the loop, the two things you look up while you are in it, and what to do once it holds.

<Info>
  **What you need.** A terminal with `curl`, an Orca account with credits, and one coding agent: Claude Code, Codex, Cursor, or anything that speaks MCP. A few read-backs use `jq`. Every command is copy-paste and works as written in bash, zsh and fish, and every one was run against `orca` CLI 0.9.0. On an older CLI, `orca update`.
</Info>

<CardGroup cols={3}>
  <Card title="Wire it up" icon="terminal" href="#wire-your-session-to-orca">
    Once per machine. Install the CLI, sign in, and hand the tools to your session.
  </Card>

  <Card title="The build loop" icon="arrows-rotate" href="#the-build-loop">
    Four moves you go round until the output holds. This is the page.
  </Card>

  <Card title="Look it up" icon="file-code" href="#the-two-files">
    Every field in the two files, and the one table that says which rule goes where.
  </Card>
</CardGroup>

***

## Wire your session to Orca

Once per machine. Your session needs the `orca` CLI and a signed-in context; everything after that is the same whichever coding agent you use.

<Steps>
  <Step title="Install and sign in">
    ```bash theme={"dark"}
    curl -fsSL https://orcapods.ai/install.sh | sh
    orca login
    orca whoami
    ```

    The installer drops a single static binary in `~/.local/bin`, with no Node and no global npm package. `orca login` opens the dashboard to authorise the CLI. Inside a coding agent it detects that there is no browser and prints a one-time code and a URL instead, which you approve on any device; the key is written to `~/.config/orca/config.json` and never passes through the chat. In CI, set `ORCA_API_KEY` and skip login entirely. Details under [Authentication](/cli/authentication).
  </Step>

  <Step title="Hand the tools to your session">
    Pick the route for your coding agent. All of them end in the same place: the session can create agents, run them, and read the results without you relaying anything.

    | Coding agent          | Route                                                                                                                                                                                                                                                     |
    | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | Claude Code           | `claude plugin marketplace add okikorg/orca-cli` then `claude plugin install orca@orca`. The plugin registers the MCP server and ships the `use-orca` skill, which teaches Claude the golden paths. See [Use Orca from Claude Code](/agents/claude-code). |
    | Claude Code, MCP only | `claude mcp add orca -- orca mcp serve`                                                                                                                                                                                                                   |
    | Codex                 | [Use Orca from Codex](/agents/codex)                                                                                                                                                                                                                      |
    | Cursor                | [Use Orca from Cursor](/agents/cursor)                                                                                                                                                                                                                    |
    | Anything else         | Point your MCP client at `orca mcp serve`, or let the session shell out to the CLI, which was built to be driven by scripts: [CLI for agents](/agents/cli).                                                                                               |

    Prefer MCP where you have it. The server exposes the control plane as typed tools and reuses the CLI's stored credentials, so the session does not have to parse terminal output or guess at flags.
  </Step>

  <Step title="Check the session can see your workspace">
    Ask it, in its own words, to run `orca whoami --json` and `orca agents list --json`. If it comes back with your organization id and your agents, it has everything it needs.

    ```bash theme={"dark"}
    orca doctor --json
    ```

    `doctor` prints one line per check with a status and, where something is wrong, the exact fix. It is the first thing to run when a session reports that a command failed, and the thing to paste back when you cannot tell why.
  </Step>
</Steps>

***

## Choose where you start

You do not have to start from a blank file. Four ways in, every one of them a command, so your coding session can drive all four without you opening a browser.

| Start from                                                           | What your session runs                                                              |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| **1. Nothing.** You describe the job, your session writes the files  | `orca skills import`, then `orca agents create -f`                                  |
| **2. A [kit](/concepts/kits) that already does the job**             | `orca kit add <link>`                                                               |
| **3. A kit that is close but not exact**                             | `orca kit add`, then `orca agents get` and `orca skills get` to pull its files down |
| **4. A kit's source in git**, before anything touches your workspace | `git clone`, then import and create                                                 |

**Route 1 is the rest of this page.** The other three are faster when someone has already built something close, and they all land in the same place: files on disk, or assets in your workspace. From there the loop below is identical, except that you are editing someone else's judgement rather than your own first draft.

### From a kit that already does the job

When a kit works as published, nothing needs editing. Hand its link to the CLI:

```bash theme={"dark"}
orca kit add https://app.orcapods.ai/kits/kit-utRCllawsrI2cqKdT --dry-run
orca kit add https://app.orcapods.ai/kits/kit-utRCllawsrI2cqKdT
```

The plan prints before anything is installed: one row per asset with the name it will take in your workspace. `--dry-run` stops there. Without it you get a confirmation prompt, and in a script `--yes` answers it; a non-interactive run without `--yes` exits `2` rather than installing something nobody saw.

Nothing you already have is ever overwritten. The server reads every name the kit carries against what you own and answers with a free one, walking `name-copy`, `name-copy-2` and upwards, and the CLI sends those names back unchanged. Adding the same kit twice gives you a second copy rather than a clobbered first one. To steer it:

```bash theme={"dark"}
orca kit add <link> --name profile:writer=my-writer   # install one asset under another name
orca kit add <link> --skip skill:seo                  # leave one asset out
```

Any schedule the kit carries arrives stopped, so a copied workspace does not start spending on a cadence you have not read. What lands is pinned on Home unless you pass `--no-pin`. From that moment the assets are ordinary agents and skills that you own:

```bash theme={"dark"}
orca agents list
orca run seo-writer "Write about connection pooling" --detach
```

<Note>
  `orca kit add` arrived in CLI 0.9.0. If `orca kit --help` does not resolve, run `orca update`.
</Note>

### From a kit you want to change

A kit is a snapshot, not a subscription, so the fastest route to a variant is to install it, read what it installed, and change the part that is wrong. Your session can do the whole thing without leaving the terminal:

```bash theme={"dark"}
orca kit add <link> --yes
orca agents get seo-writer --json > agents/seo-writer.json
orca skills get seo-engine --json | jq -r '.resources[].path'
orca skills get seo-engine --json | jq -r .body > skills/seo-engine/SKILL.md
orca skills get seo-engine --resource references/writing-rules.md > skills/seo-engine/references/writing-rules.md
```

The first line writes a document you can edit and feed straight back to `orca agents update -f`. The second lists the skill's bundled files so your session knows what to fetch. The last two write the body and one reference to disk; `--resource` sends the file's contents to stdout exactly as stored, so it redirects cleanly.

Two things to know before you edit. A round-tripped agent document carries server-computed fields the CLI does not model, so it imports fine but must not be combined with `--strict`. And importing a skill under a name that already exists is a usage error pointing at `--force`, which is what you want when iterating on your own copy and not what you want when you meant to create a variant; rename it in the frontmatter first.

### From a kit's source in git

The one route where you read everything before anything reaches your workspace. Good when you want the method rather than the product, and good when you want the files in your own repo from the start:

```bash theme={"dark"}
git clone https://github.com/okikorg/orca-kits
cd orca-kits/kits/seo-helper
```

Then the same two commands as route 1, which is the whole point of a kit having a source you can read:

```bash theme={"dark"}
orca skills import ./skills/seo-engine
orca agents create -f agents/seo-writer.yaml
orca agents create -f agents/seo-media.yaml
```

`seo-helper` is two agents that share a workspace, so it also needs a pod; its README names which agent leads and what to call the pod. Every kit follows this layout, so `agents/` and `skills/` are always where you expect them.

***

## The build loop

Four moves. You do the first two once and the last two as many times as it takes, which for a job worth automating is usually two or three.

Everything here rests on one fact about the shape of an agent, so it is worth having before the first move: **an agent is two files.** An agent document owns the shape of one answer, and a [skill](/concepts/skills) owns the judgement every agent of that kind should share. You do not need the detail to make the first ask; when you want it, it is in [The two files](#the-two-files).

### 1. Describe the job

A good ask names four things: **the job, the exact shape of the answer, where each rule belongs, and the runtime.** The shape matters most. An agent whose output has a fixed form is one you can check without reading carefully, which is what makes the third and fourth moves fast rather than a matter of taste.

Fill this in and paste it into your session:

```text theme={"dark"}
Read https://docs.orcapods.ai/cli/agent-documents first, it is the schema.

Build me an Orca agent called <name>.

Job: <what it does, in one sentence, and for whom>
Input: <what arrives in the prompt, and in what form>
Output: <the exact shape. Name the sections, the order, and the last line.
         If the form is fixed, say it is fixed and that nothing may come
         before or after it.>
House rules: <the judgement calls: what counts, what is out of scope, the
         vocabulary, what must never appear. Put these in a skill rather
         than in the system prompt, because every agent of this kind will
         share them.>
Runtime: marlin, sandboxed, on a cheap model.

Write two files, agents/<name>.yaml and skills/<skill>/SKILL.md.
Show me both. Do not create anything yet.
```

Two instructions in there earn their place. **"Show me both, do not create anything yet"** keeps the files in your repo, where you can read them, diff them and commit them, rather than inside a workspace you later have to export. **"Put these in a skill rather than in the system prompt"** is the split stated where the session will act on it; without that line you get one long system prompt that works and cannot be reused.

The first answer is usually eighty percent right, and the missing twenty is always in the same places. Push back on:

* **A vague `description` on the skill.** If it does not say when to use the skill, the model will not open it at the right moment. Ask for the triggers.
* **Rules in the wrong file.** Anything that would apply to the next agent of this kind belongs in the skill. Anything about this answer's form belongs in the prompt.
* **An invented or unpriced model id.** Ask it to check a real list rather than recall one. An id the server cannot price quarantines the run.
* **A `references/` folder on a marlin agent.** Marlin reads the body only; see [The skill](#the-skill).
* **Tools it did not need.** Every extra bundle is surface area. A question-answering agent does not need `@orchestration`, and an agent you plan to publish should not carry introspection.
* **A system prompt that explains rather than instructs.** "You should try to be concise" is not a contract. "Answer in exactly two lines, nothing before or after them" is.

### 2. Create them

Import the skill first, then create the agent that names it. The server checks that the skill exists at create time.

```bash theme={"dark"}
orca skills import ./skills/my-method --dry-run
orca skills import ./skills/my-method
orca agents create -f agents/my-agent.yaml
```

Import is two-phase. The dry run uploads the package for validation and reports the skill name, the number of resource files, the total bytes, and whether it requires a sandbox, without registering anything. Validation errors print to stderr as `error: ...` and exit `2`; warnings print and do not block. The directory must contain `SKILL.md` at its root, and every file under it is uploaded recursively, so the folder's own name does not have to match the skill's name.

`agents create` validates the document's shape locally first, so problems come back as a list under `invalid agent document` with exit `2`. What the server owns is checked server-side: whether the model id is priced, and whether the skills exist. To pipe a document your session printed into the chat rather than wrote to disk, `-f -` reads stdin, and stdin must be a pipe:

```bash theme={"dark"}
cat agents/my-agent.yaml | orca agents create -f -
```

Then read it back, to confirm the skill attached and the runtime and worker mode agree:

```bash theme={"dark"}
orca agents get my-agent --json | jq '{runtime, model, skills, tools, workerMode}'
```

Two agents that hand work to each other need a [pod](/concepts/pods), which is one more command. Members write to `/pools/my-pod/...` and read each other's output there:

```bash theme={"dark"}
orca pools create my-pod --member my-agent:lead --member my-helper
```

The role rides on the member, written `profile:role`, and `--member` repeats. A member given no role joins as `member`.

### 3. Test it on input built to break it

Test on input you can check at a glance, and build it to break the agent rather than to flatter it. Half of what an agent gets wrong is what it kept, not what it wrote.

A good test input has three parts, and the third is the one people leave out.

1. **Ordinary cases**, enough to see the normal shape.
2. **One near-miss**: something that belongs in a different bucket than it first appears, which tests the judgement the skill encodes.
3. **Things that must not appear at all**, which test what the agent drops. An agent that never drops anything has no judgement; it has a formatter.

Write down what must be true of the answer *before* you run it. Three invariants is usually enough, and each should be checkable in seconds: the shape held, the near-miss landed in the right place, the excluded items are named as excluded rather than quietly missing.

```bash theme={"dark"}
orca run my-agent "<the instruction>

$(cat input.txt)"
```

Then run the same input twice more. Once is not a result, and a shape that holds on one run and drifts on the next is a prompt problem rather than luck. Every second time round the loop, change the input to something the agent has not seen; an agent tuned on one input is tuned to that input, and you will not find out until it meets real work.

[Reading a run](#reading-a-run) has the mechanics: detaching, tailing, checking invariants in a script, and what the run cost.

### 4. Name the defect, change one file

Your session cannot see the run. Give it the input and the output verbatim, then say what is wrong in terms of the contract rather than in terms of the edit you have in mind:

```text theme={"dark"}
Here is the input and what it produced.

<paste the input>
<paste the full answer>

Two defects. <the first, described as a breach of the contract>
<the second>

Fix one at a time. Tell me which file each belongs in before you change it.
```

Naming the defect rather than the fix matters more than it sounds. "Add a rule about performance changes" produces a rule that fires on the word performance. "It put this under Added and it is a Changed" lets the session find the actual gap, which is usually that the skill never defined the categories at all. Which file the fix belongs in is a table: [Which rule goes where](#which-rule-goes-where).

Both updates are idempotent, so applying a change is two commands:

```bash theme={"dark"}
orca agents update -f agents/my-agent.yaml
orca skills import ./skills/my-method --force
```

`agents update` replaces the whole profile with the document and targets the `name` inside the file; pass a different name as a positional to rename an existing agent. `--force` is required to overwrite a skill that already exists. To see what has already been tried this session:

```bash theme={"dark"}
orca agents changes my-agent --limit 5
```

Then go back to move 3 with the same input.

### Going round again

Four rules keep the loop converging instead of wandering.

* **One change per turn.** Two edits and a better result tells you nothing about which edit did it.
* **Ask for a diff, not a rewrite.** A session that regenerates the whole file each turn will quietly drop an edit you made by hand two turns ago.
* **When two rules start fighting, the skill is too long.** If the model keeps trading one rule off against another, cut the weaker rule instead of adding a third to arbitrate.
* **Keep both files in your repo.** They are the artefact; the workspace copy is a deployment of them, and `orca agents get --json` rebuilds it.

If your session has the Orca plugin or the MCP server, it can run moves 2 to 4 itself: make the edit, re-import, run the same input, and report only whether your invariants held. What you must keep doing yourself is reading the output.

**You are done** when three consecutive runs, on input the agent has not seen, hold every invariant you named, and the only changes left are ones two colleagues would disagree about. That is the honest bar. Chasing the last stylistic tweak in a skill costs more than editing the occasional line of output by hand.

***

## The two files

Reference for while you are in the loop. The agent document is one agent; the skill is a method several agents can share.

### The agent document

A YAML or JSON file describing one agent. The CLI validates its shape locally before anything is sent, so a typo comes back as a field-level message rather than a `400` from the server. Every field is in [Agent documents](/cli/agent-documents); these are the ones that decide how the agent behaves.

| Field          | Required | What it decides                                                                                                                |
| -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `name`         | yes      | Unique in your workspace. It is how the CLI, the SDKs and any pod refer to the agent, so pick one you will not want to change. |
| `runtime`      | yes      | Which engine runs the loop: `pi`, `claude`, `codex`, `vercel` or `marlin`.                                                     |
| `model`        | no       | The model id in the form the runtime expects. The server rejects an id it cannot price.                                        |
| `systemPrompt` | no       | Who the agent is, and the shape of one answer. Stays short when a skill carries the rules.                                     |
| `skills`       | no       | Skill names to attach. Each must already exist in the catalog.                                                                 |
| `tools`        | no       | Tool selectors. Omitted means the default safe toolkit.                                                                        |
| `mcpServers`   | no       | Per-agent MCP servers, inline or a catalog reference to a [connected app](/concepts/connected-apps).                           |
| `fs`           | no       | Extra filesystem grants and denies on top of the agent's own home at `/agents/{self}/**`.                                      |
| `workerMode`   | no       | `static` by default, or `sandbox` to boot a per-session worker.                                                                |
| `sandbox`      | no       | Provider, image, CPU and memory, idle timeout.                                                                                 |

Any other top-level key produces a warning naming the key and is dropped rather than sent. With `--strict` those warnings become errors and the command exits `2`, which is what you want in CI and usually not what you want while iterating.

**The runtime** is the field people get wrong first, because all five work and they fail differently.

| Runtime  | Use it when                                                                                                                                                |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `marlin` | The default for new agents. Orca's own harness, tuned so more of each token goes to the task and less to the machinery around the model. Always sandboxed. |
| `pi`     | The pi.dev coding agent, for jobs that look like coding work in a real file tree.                                                                          |
| `claude` | You want the Claude Agent SDK's own behaviour, including its skill activation model.                                                                       |
| `codex`  | The OpenAI Codex SDK path.                                                                                                                                 |
| `vercel` | The Vercel AI SDK path, and the widest provider choice.                                                                                                    |

Two lines travel together for the default. `runtime: marlin` requires `workerMode: sandbox`, because marlin never runs unisolated, and its model ids carry the gateway they go through:

```yaml theme={"dark"}
runtime: marlin
model: openrouter:anthropic/claude-haiku-4.5
workerMode: sandbox
```

The dashboard's YAML import enforces that marlin model ids are prefixed `openai:`, `anthropic:` or `openrouter:`. The CLI does not, so an unprefixed id passes local validation and is rejected server-side.

**Tools** are named tools, `@bundle` sentinels, or `prefix_*` wildcards. `@default` is the safe baseline and is what an omitted field means:

```bash theme={"dark"}
orca bundles
```

```text theme={"dark"}
@default          Safe baseline: introspection, fs, pool, plus utilities.
@introspection    Runner and agent state (runner_info, list_sessions).
@orchestration    Delegate, submit_workflow_run, wait_workflow_run, repair_workflow_run.
@memory           Agent Memory Bank + auto-injection of context.
@sandbox          Ephemeral per-session compute environment (bash, file tools).
@artifacts        Shared artefact store: save_artifact, get_artifact.
```

Three things about tools are worth knowing before your session guesses at them.

`@default` already includes `web_search` and `web_extract`, through `@introspection`. It also includes introspection tools that can read the workspace's own agents and sessions, which is fine for an internal agent and wrong for one you intend to [publish](/concepts/publishing) to a public endpoint. For a public agent, name the tools you want explicitly instead of taking the bundle.

`@memory` is opt-in and does two things at once: it registers the four memory tools and it turns on a `--- CONTEXT FROM MEMORY ---` block prepended to every run. The bank is scoped per agent profile rather than per project, so one agent serving two jobs will see both jobs' memories in every run.

Wildcards match within one dot-separated segment, so `web.*` compiles to `^web\.[^.]+$`. The registered tools are named with underscores, such as `web_search`, so that selector matches nothing and the agent loses its web tools silently. Name tools exactly, or take the bundle.

### The skill

A folder with a `SKILL.md` at its root, plus whatever it needs:

```text theme={"dark"}
skills/my-method/
  SKILL.md              frontmatter, then the method
  references/*.md       the detail, read on demand
  scripts/*             executables, which require a sandbox on the agent
```

The frontmatter is two fields, and the second one is load-bearing:

```markdown theme={"dark"}
---
name: my-method
description: What this does and when to use it. Written for the model deciding whether to open it, not for a human browsing a catalog.
---
```

The `description` is what the model sees before it has read anything else, so it should name the triggers rather than the topic. "Use whenever you are asked to summarise, triage or reply to a customer support thread" beats "Support helper", because the first tells a model when to reach for the skill and the second only tells it what to call it. A skill nobody opens at the right moment may as well not be attached.

<Warning>
  **Where the references actually get read depends on the runtime.** On `runtime: marlin` the skill body is composed into the system prompt before every run, and the agent has no tool for fetching the skill's other files, so a marlin skill must be complete in its `SKILL.md`. On `pi`, `claude`, `codex` and `vercel` the agent sees a catalog of names and descriptions, calls `activate_skill` when one becomes relevant, and reads bundled files with `read_skill_resource`.

  A multi-file skill is worth writing for those runtimes and is silently half-loaded on marlin. If your session produces a `references/` folder for a marlin agent, tell it to fold them into the body or change the runtime.
</Warning>

A skill that bundles `scripts/` needs the agent to have a sandbox enabled. The import reports `requiresSandbox`, so you find out before you attach it rather than during a run.

### Which rule goes where

The question that settles almost every case: **would the next agent you build want this rule too?** If yes it is the skill's, if no it is this agent's. In practice a defect lands in one of five places.

| What went wrong                                                                                           | Where it belongs                                                                  | Why                                                                                            |
| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| The shape drifted: a missing section, the wrong order, a final line absent or reworded                    | The **system prompt**                                                             | The shape is this agent's contract for one answer, and nothing else should depend on it.       |
| The judgement was wrong: what counts as in scope, how an entry reads, a banned word, a category's meaning | The **skill**                                                                     | It is a house rule, and the next agent of this kind should inherit it.                         |
| It invented a number, a link or a name                                                                    | The **system prompt**, as a hard rule, and check that the input really carried it | Hallucination rules are worth repeating in both places; this is the one duplication that pays. |
| It did the job correctly on the wrong thing                                                               | **Your prompt**, not the agent                                                    | An agent that follows a vague instruction precisely is working as specified.                   |
| It was right, but too slow or too expensive for the job                                                   | The **model** field                                                               | Try the cheap model first, and move up only when the output, not the feeling, says to.         |

Get this right and the second agent of that kind is a fifteen-line file. Get it wrong and you paste the same paragraph into every agent until the copies disagree with each other, which is a bug you discover months later in production output.

***

## Reading a run

The other half of the reference: what the CLI gives you back, and how a session checks an answer without you reading it.

In a terminal a run renders as a live transcript, assistant text and tool calls as they happen, ending in a status line with the run id, elapsed time and token usage. The exit code follows the run: `0` on `ok`, `1` on `error`, `cancelled` or `interrupted`. Ctrl-C detaches the tail only, exit `130`; the run keeps going server-side, and stderr prints the commands to reattach or stop it.

**In a script**, `--json` makes every run event one JSON object per line, which is what lets your session check invariants rather than you eyeballing them:

```bash theme={"dark"}
orca run my-agent "..." --json | jq -r 'select(.type == "assistant") | .message'
```

Each line carries a `type` of `progress`, `result`, `error`, `assistant`, `tool_call`, `tool_result` or `usage`, plus the fields that apply to it. A `usage` object carries `inputTokens`, `outputTokens`, `cacheReadTokens` and `cacheCreateTokens`.

**In the background**, `--detach` prints the run id and returns your prompt. Without it the id appears only on stderr, so use it whenever a script needs to capture one:

```bash theme={"dark"}
RUN_ID=$(orca run my-agent "..." --detach)
orca runs tail "$RUN_ID"
orca runs get "$RUN_ID" --json | jq '.events[] | select(.type == "tool_call") | .toolName'
```

`runs tail` replays buffered events first, so tailing a finished run prints its whole transcript, and a dropped connection reconnects without printing anything twice.

**What it cost.** A run has no price of its own; the session it ran in does. `orca run` opens a fresh session per run unless you pass `--session`, so one run is usually one session:

```bash theme={"dark"}
orca sessions list --json | jq -r '.[0] | [.profile, .costUsd, .costState] | @tsv'
```

```text theme={"dark"}
my-agent   0.004812   estimated
```

`estimated` means the run is priced from the recorded rate schedule and has not been reconciled against the provider's bill yet, so treat it as close rather than final. `orca usage --window 24h --meter cost` answers the different question of where your credit went. Details under [Credits and billing](/concepts/billing).

**Exit codes** are what let a session act on a failure rather than just report it:

| Code  | Meaning                                                                                         |
| ----- | ----------------------------------------------------------------------------------------------- |
| `0`   | Success                                                                                         |
| `1`   | API or network failure, or a tailed run that ended in any status other than `ok`                |
| `2`   | Usage error: a bad document, a missing required argument, a destructive command without `--yes` |
| `3`   | Auth: no key configured, or a `401` or `403`                                                    |
| `4`   | Not found                                                                                       |
| `130` | Interrupted                                                                                     |

***

## Ship it

The agent is ordinary from here: it has [sessions](/concepts/sessions), it shows up under **Agents** in the dashboard with a task box, and it can be reached three ways.

**Put it behind an endpoint** your product calls, with its own keys, separate from your tenant key:

```bash theme={"dark"}
orca agents publish my-agent --slug my-agent
orca agents keys create my-agent --label my-app
```

The [publishing guide](/guides/publishing) covers conversations, tool events, visibility and per-agent spend caps. The chat key travels in the `Authorization` header and is the only credential your product needs.

**Put it on a schedule**, so it runs on a cadence instead of when you remember. A firing creates an ordinary run through the same gates, and carries a short memory note between firings so the next run does not start blind. See [Automations](/concepts/automations).

**Share it** as a [kit](/concepts/kits), agent and skill together, as a link anyone can copy into their own workspace in one action. The link works for people who have never heard of Orca.

**Give it a second job.** The same skill with a different agent document is a different worker sharing the same judgement. That is the whole point of having split them, and it is where the loop pays for itself.

<CardGroup cols={2}>
  <Card title="Orca kits" icon="github" href="https://github.com/okikorg/orca-kits">
    Complete kits you can copy into your workspace, agent documents and skills included.
  </Card>

  <Card title="Agent documents" icon="file-code" href="/cli/agent-documents">
    Every field in the YAML: tools, MCP servers, connected apps, memory, sandboxes and file mounts.
  </Card>

  <Card title="Skills" icon="book" href="/concepts/skills">
    What a skill is, what it may bundle, and when its scripts need a sandbox.
  </Card>

  <Card title="Start here" icon="rocket" href="/start-here">
    The by-hand version: one agent, an endpoint, and the same job on a second runtime.
  </Card>
</CardGroup>
