Skip to main content
The 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.
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.

Wire it up

Once per machine. Install the CLI, sign in, and hand the tools to your session.

The build loop

Four moves you go round until the output holds. This is the page.

Look it up

Every field in the two files, and the one table that says which rule goes where.

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

Install and sign in

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

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

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

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. 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:
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:
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:
orca kit add arrived in CLI 0.9.0. If orca kit --help does not resolve, run orca update.

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:
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:
Then the same two commands as route 1, which is the whole point of a kit having a source you can read:
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 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.

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:
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.
  • 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.
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:
Then read it back, to confirm the skill attached and the runtime and worker mode agree:
Two agents that hand work to each other need a pod, which is one more command. Members write to /pools/my-pod/... and read each other’s output there:
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.
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 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:
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. Both updates are idempotent, so applying a change is two commands:
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:
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; these are the ones that decide how the agent behaves. 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. 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:
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:
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 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:
The frontmatter is two fields, and the second one is load-bearing:
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.
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.
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. 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:
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:
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:
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. Exit codes are what let a session act on a failure rather than just report it:

Ship it

The agent is ordinary from here: it has 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:
The publishing guide 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. Share it as a kit, 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.

Orca kits

Complete kits you can copy into your workspace, agent documents and skills included.

Agent documents

Every field in the YAML: tools, MCP servers, connected apps, memory, sandboxes and file mounts.

Skills

What a skill is, what it may bundle, and when its scripts need a sandbox.

Start here

The by-hand version: one agent, an endpoint, and the same job on a second runtime.
Last modified on September 12, 2026