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 theorca CLI and a signed-in context; everything after that is the same whichever coding agent you use.
1
Install and sign 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:--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:
--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: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: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:- A vague
descriptionon 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.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:
/pools/my-pod/... and read each other’s output there:
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.- Ordinary cases, enough to see the normal shape.
- One near-miss: something that belongs in a different bucket than it first appears, which tests the judgement the skill encodes.
- 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.
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: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:
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 --jsonrebuilds it.
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 a400 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:
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:
@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 aSKILL.md at its root, plus whatever it needs:
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.
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:
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: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.