The agent protocol
ovld protocol is the authoritative interface between an agent and Overlord.
The same operations are available from the CLI, the hosted API, and the
MCP surface — drift between them is treated as a bug.
This page is the lifecycle you follow while executing a mission.
The lifecycle at a glance
Section titled “The lifecycle at a glance”attach ──► update / heartbeat ──► (ask, if blocked) ──► deliver │ (repeat) │ └── begins a session, returns full context └── ends the session, moves objective to complete, mission to reviewTwo ways you arrive on a mission
Section titled “Two ways you arrive on a mission”Mode 1 — launched onto a mission. The prompt already contains a mission id or says the session was started by Overlord. Attach immediately and begin the objective.
Mode 2 — asked from chat to use Overlord. A normal conversation where the user asks you to create, inspect, or run Overlord work. Create or inspect, and only attach when the user explicitly says to execute.
Addressing a mission or an objective
Section titled “Addressing a mission or an objective”Every ovld protocol subcommand that takes --mission-id also takes
--objective-id (an objective UUID, or a display id such as coo:312.k7xm).
An objective display id already names its mission — coo:312.k7xm contains
coo:312 — so --mission-id is optional whenever you pass one:
ovld protocol update --objective-id coo:312.k7xm --summary "Refactored the parser."ovld protocol deliver --objective-id coo:312.k7xm --summary "Done."Reach for the objective form when reconnecting to a mission that is running more
than one objective. There, the mission id no longer identifies a unit of work,
and commands that rediscover “the active objective” (attach, load-context,
connect) return ambiguous_active_objective until you name one.
An objective UUID carries no parent mission, so pass --mission-id
alongside it.
The CLI fills --objective-id in from OVERLORD_OBJECTIVE_ID on session-scoped
subcommands, so a launched agent rarely types it. Two commands never inherit it:
update-objective, where the id names the objective being changed, and
discuss-objective, which wants a draft rather than the objective already
executing.
Launch, queue, and inspect by objective
Section titled “Launch, queue, and inspect by objective”These protocol commands take --objective-id (UUID or display id) as their
primary argument. A display id is enough on its own:
ovld protocol launch-objective --objective-id coo:312.k7xm --agent claudeovld protocol list-deliveries --objective-id coo:312.k7xmovld protocol queue-objective --objective-id coo:312.k7xmovld protocol dequeue-objective --objective-id coo:312.k7xmovld protocol update-objective --objective-id coo:312.k7xm --no-auto-advancelaunch-objectivequeues a normal execution request for a runner. It does not attach the calling agent. Required:--objective-id,--agent. Optional:--model,--reasoning-effort,--execution-target-id.list-deliveriesreturns one mission’s newest-first normalized deliveries (summary, verification, follow-up notes, delivery-report evidence — never raw payload JSON). A display id supplies the mission.queue-objectiveadds or moves the objective in the project’s Run Queue (delivery-driven sequencing, not a direct launch). Optional--queue,--after(queued entry, objective UUID, or display id),--front, and one-based--position; choose at most one placement flag.dequeue-objectiveremoves it from the queue. Already-unqueued objectives return{ removed: false }.retry-queue-entryretries one held entry: it clears the hold and resets the attempt budget so the dispatcher tries again on the next tick. Address it with--objective-idor--entry; an entry already dispatched or running is refused.run-queuereads every live queue and entry from--project-id,--objective-id, or--mission-id, optionally narrowed with--queue.reorder-run-queueatomically replaces one queue’s complete entry order; every live entry is required exactly once and running/dispatched entries cannot move.create-run-queue,update-run-queue,delete-run-queue, andreorder-project-run-queuesmanage queue definitions. New queues start paused; explicitly resume one or directly launch a queued objective to start it. Queue-definition operations requireproject:update; entry operations requireexecution_request:create.reorder-future-objectivestakes--mission-idand--ordered-objective-ids-jsonwith every future objective UUID in the desired order. Display ids are not accepted there.
Hosted MCP exposes the same operations as overlord_launch_objective,
overlord_list_deliveries, overlord_list_run_queues,
overlord_reorder_run_queue, overlord_queue_objective (remove: true to
dequeue), overlord_manage_run_queue, and overlord_reorder_future_objectives.
Attach
Section titled “Attach”ovld protocol attach --mission-id coo:312 --objective-id coo:312.k7xmovld protocol attach --objective-id coo:312.k7xmPass --objective-id when you already know which objective to execute — attach
will not rediscover another one. Runner launches export OVERLORD_OBJECTIVE_ID
and the CLI forwards it automatically. Mission-only attach still selects the
current active objective, as long as only one is active.
The response prints JSON containing session.sessionKey. The CLI also persists
that key for the working directory, so later ovld protocol commands resolve it
without --session-key. If auto-resolution fails, pass
--session-key <sessionKey> explicitly on every call.
The attach payload gives you everything a fresh agent needs to continue without reading prior chat:
objective— the current task body is inobjective.objective. Treat it as authoritative for the goal, constraints, and delivery target.previousObjectives/futureObjectives— completed and upcoming steps.history,artifacts,attachments,sharedState— structured context.projectResources— the project’s logical resources resolved for the execution target, each with aresourceKey,path, andstate. When a project spans repositories, siblings are read-only context unless a future objective launches in them.agentInstructions— concise workflow guidance and pointers into the structured fields.
attach stores an exact objective/session binding for local connector evidence.
It does not read Git state or derive a worktree baseline.
Post progress while you work
Section titled “Post progress while you work”Send a real narrative update when something meaningful happens:
ovld protocol update --session-key <sessionKey> --mission-id coo:312 \ --summary "Implemented the loading state and wired it to the query hook." \ --phase executeDuring long mechanical stretches with nothing to narrate, send a liveness heartbeat instead — it updates the session without creating a feed event:
ovld protocol heartbeat --session-key <sessionKey> --mission-id coo:312 \ --phase execute --note "Running the integration suite"Post at least one update before delivering.
Phases and event types
Section titled “Phases and event types”--phase accepts: draft, execute, review, deliver, complete,
blocked, cancelled. --event-type accepts: update (default),
user_follow_up, alert, discussion_summary, decision. Use decision or
discussion_summary to make an important non-file decision visible on the
mission.
Ask when blocked
Section titled “Ask when blocked”If you cannot proceed without a human decision, post the question and stop:
ovld protocol ask --session-key <sessionKey> --mission-id coo:312 \ --question "Should the loading state block the whole page or just the panel?"Do not guess past a genuine fork in requirements. Asking is cheaper than delivering the wrong thing.
Deliver
Section titled “Deliver”Delivery is the concluding step. It stores the summary and optional current
annotations, moves the objective to complete, and moves the mission to review.
ovld protocol deliver --session-key <sessionKey> --objective-id coo:312.k7xm \ --summary "Added a loading state to the account page and covered it with a test."Structured delivery evidence
Section titled “Structured delivery evidence”Include optional deliveryReport.agentReport evidence in --payload-json or
--payload-file when it helps the reviewer: humanActions, tradeoffsMade,
knownRisks, deferredWork, and assumptions. Use empty arrays when there is
nothing to report. Human actions must be real user follow-up work — never Git
operations or routine testing/review.
Delivery remains immediate: Overlord stores a deterministic report first, then may compose a clearer presentation asynchronously. The original summary is never replaced.
Changed files are captured for you
Section titled “Changed files are captured for you”You do not enumerate changed files or inspect git status for delivery. An
objective-bound connector callback records only paths directly named by its
native edit payload. The CLI synchronizes that local ledger separately from the
delivery request. Shell and no-path callbacks record unavailable hook health;
they never trigger a worktree scan.
Rationales are optional reviewer annotations, not coverage requirements. When a
rationale is useful, each entry uses the canonical fields filePath, label,
summary, why, and impact, plus optional hunks containing only header.
Do not wrap an entry, use a snake-case alias, or send a file_changes artifact.
Unknown keys discard only that advisory entry with a bounded warning; the last
valid entry wins when a canonical path is repeated.
Preflight before delivering
Section titled “Preflight before delivering”Run the local-only preflight first. It drains the exact objective ledger and reports remaining evidence plus bounded hook health; it never scans or classifies the shared worktree:
ovld protocol changes --objective-id coo:312.k7xmLarge payloads and special characters
Section titled “Large payloads and special characters”Inline --*-json values are rejected above ~8 KB. For large arrays, stream on
stdin with --change-rationales-file - (or --payload-file -). When a summary
or question contains backticks, $vars, or other shell-special characters, use
--summary-file - / --question-file - with a single-quoted heredoc:
ovld protocol deliver --session-key <sessionKey> --mission-id coo:312 \ --summary-file - <<'EOF'Refactored `useAccount()` to expose `isLoading`; see $PR for details.EOFShared worktree safety
Section titled “Shared worktree safety”The working tree may hold changes from other agents, missions, or objectives running in the same checkout. Those are not yours to undo.
If git status shows unrelated dirty paths:
- Leave those files intact.
- Do not fabricate a rationale for work you didn’t do.
- Run
ovld protocol changes --objective-id <objective>to inspect only the current objective’s recorded evidence. - Deliver the summary normally. Unrelated worktree state is not a delivery input and cannot block the lifecycle transition.
After delivery
Section titled “After delivery”Delivery ends implementation. Do not keep editing unless the user explicitly asks for follow-up work.
- Ordinary follow-up questions stay in discussion mode; connector hooks
record them as
user_follow_upactivity — you don’t post those manually. - Explicit follow-up implementation on a delivered mission:
- If a live session still accepts updates:
ovld protocol update --begin-follow-up-work --follow-up-intent execution --summary "Beginning follow-up work." - If no live session exists:
ovld protocol resume-follow-up --mission-id <id> --summary "Beginning follow-up work."and use the returned session key.
- If a live session still accepts updates:
- During follow-up execution, post updates and record change rationales just like the first pass, then deliver again.
Create an artifact during a turn
Section titled “Create an artifact during a turn”Artifacts do not require delivery. Publish a plan, notes, decision, or URL mid-session, then revise it later if needed:
ovld protocol add-artifact \ --mission-id coo:312 \ --type note \ --label "Implementation plan" \ --content-text-file -Provide --type, --label, and at least one of --content-text /
--content-text-file or --external-url. An optional --session-key
(auto-injected from the attach cache when present) stamps session/objective
provenance; --objective-id does the same when you have no live session, and
the session key wins when both are given. Hosted MCP exposes the same call as
overlord_add_artifact.
Update an existing artifact
Section titled “Update an existing artifact”When a later objective or follow-up must revise a plan, notes, or URL artifact created earlier, update that artifact in place instead of delivering a duplicate:
ovld protocol update-artifact \ --mission-id coo:312 \ --artifact-id <artifact-id> \ --expected-revision 2 \ --label "Revised plan" \ --content-text-file -Use the id and revision from attach / load-context artifacts or
ovld mission artifacts. Provide at least one of --label,
--content-text / --content-text-file, or --external-url. No session key is
required. Stale --expected-revision returns a conflict — refresh and retry.
Hosted MCP exposes the same call as overlord_update_artifact.
Missions vs objectives
Section titled “Missions vs objectives”A mission is a whole feature or goal. An objective is one agent pass — one prompt. Create a new mission for a distinct goal; add objectives to an existing mission for sequential steps toward the same goal:
ovld protocol add-objectives --mission-id coo:312 \ --objectives-json '[{"objective":"Implement the API"},{"objective":"Add CLI docs"}]'Command quick reference
Section titled “Command quick reference”| Command | Purpose |
|---|---|
attach |
Start a session, return full context. Begin work. |
connect |
Lightweight session without full context assembly. --objective-id pins it. |
load-context |
Read mission context without a session (inspection only). --objective-id selects the objective. |
list-deliveries |
Read one mission’s normalized deliveries. An objective display id supplies the mission. |
launch-objective |
Queue a runner execution. Requires --objective-id (UUID or display id) and --agent. |
reorder-future-objectives |
Replace one mission’s complete future-objective UUID order. |
run-queue |
Read live Run Queues from project, objective, or mission scope. |
reorder-run-queue |
Atomically replace one Run Queue’s complete entry order. |
queue-objective |
Add or move one objective in the Run Queue. Requires --objective-id. |
dequeue-objective |
Remove one objective from the Run Queue. Requires --objective-id. |
retry-queue-entry |
Retry one held Run Queue entry. Requires --objective-id or --entry. |
create-run-queue |
Create a paused queue definition; requires project:update. |
update-run-queue |
Rename, pause, or resume a queue; requires project:update. |
delete-run-queue |
Delete a queue definition; requires project:update. |
reorder-project-run-queues |
Replace the complete queue-definition order; requires project:update. |
discover-project |
Resolve the project from cwd, id, or directory. |
search (search-missions alias) |
Find missions by query, state, project. |
statuses |
List one project’s board columns. |
discuss-objective |
Submit a draft objective for discussion (no session). --objective-id names which draft. |
create / prompt |
Create a draft / create-and-attach a mission. |
add-objectives |
Append ordered objectives to a mission. |
update-objective |
Turn auto-advance on or off, or edit instruction text. Requires --objective-id. |
update |
Post progress, decisions, and optional rationales. |
heartbeat |
Liveness ping, no feed event. |
ask |
Post a blocking question and stop. |
deliver |
Finish: summary, artifacts, rationales, mark complete. |
changes |
Local preflight of changed-file attribution. |
resume-follow-up |
Reopen a delivered objective for follow-up. |
read-context / write-context |
Read or store persistent shared context. |
add-artifact |
Create a mission artifact mid-turn (no delivery required). |
update-artifact |
Revise an existing mission artifact in place. |
For the full CLI surface — management commands, the runner, project linking —
see the CLI reference. Never invent protocol subcommands; run
ovld protocol help when unsure.
