Documents, tools, and artifacts
Platform capabilities reach your agent as MCP tools, not protocol extensions. The worker passes an MCP server in session/new.mcpServers with a short-lived, session-scoped token already embedded. Your agent connects with any MCP client, or just uses the tools if your framework auto-discovers them.
The server is offered over stdio (every ACP agent must support stdio MCP servers). Agents that advertise mcpCapabilities.http get the HTTP transport directly. The server resolves tools from the active step: Plan, Research, and Review get their scoped artifact and guidance tools, Review also gets report_workflow_verdict, and report_result is registered for every mode. one harness dev uses the same tool names and parameters as production turns.
Workflow artifacts
Each linked task keeps one canonical artifact per workflow artifact type, addressed by a target parameter: "plan", "research", "review", or "code_summary". Your agent never needs to track an artifact's storage ID. Artifacts are structured as addressable blocks, and six tools operate at block level, so a step changes only the blocks it names: list_artifact_blocks, load_artifact_blocks, append_artifact_block, replace_artifact_block_body, update_artifact_block_metadata, and find_related_blocks. Pass the revision from a list, load, or earlier write as expectedRevision, and a write to a block that changed since then is refused with block_revision_conflict instead of overwriting it. See the MCP tool reference for their exact parameters.
A task's manually linked documents (specs, requirements, and similar material a person attached) are separate and have their own list_linked_documents / read_linked_document tools. Each entry carries a source: "linked" for material a person attached, and "task_content_document" for the task's own description, which is listed as a fallback but is already returned in full by get_task_details. read_linked_document only reads IDs on that list; an ID mentioned in the task text is not readable until someone links it to the task.
A plan turn fulfills its contract with calls like:
append_artifact_block { "target": "plan", "id": "PLAN-TASK-003", "type": "implementation_task", "title": "Separate pass-scoped retry accounting", "markdownBody": "Extract the retry accounting into pass-scoped counters in retry.py."}
Block ids are unique per artifact, so appending a block with an id that already exists is rejected. type: "summary" is the deliberate exception: it upserts in place and moves the block to the top, so a step can rewrite its summary as the last thing it does and still have it render first.
type is a closed vocabulary and is validated on write. An unrecognized type is rejected rather than stored, because a block with an unknown type falls out of every selector that reads the artifact.
| Artifact | Written by | Common block types |
|---|---|---|
| Plan | plan turns | goal, requirement, implementation_task, decision, risk, open_question, summary |
| Research | research turns | research_question, context, existing_solutions, approach, findings, options, tradeoffs, recommendation, open_questions, sources, summary |
| Review | review turns | review_finding (severity + lifecycle status), summary |
| Result summary | code turns | implementation_note, fixed_finding, blocker |
Expected inputs and outputs are declared per workflow step and enforced by the tools: a code step can read review findings but not rewrite the review artifact.
Never rewrite whole workflow artifacts, and never commit artifact files into the product repository. Operate at block level through the tools above.
Review verdicts
Review turns first derive one primary target from trusted expected inputs. Code changes, a commit, or a pull request select implementation; otherwise a plan selects plan; otherwise research selects research. A direct assignment that cannot be classified keeps a generic declared-subject fallback.
The agent then calls get_review_guidance with that target, any earlier research or plan artifacts available as supporting evidence, and only the material technical concerns. The result composes the applicable evidence relationships and review methods without a hard-coded matrix of artifact combinations. When research is the target or supporting evidence, the agent also calls get_research_guidance to judge the relevant expected outputs, questions, and criteria.
The primary target controls scope. Supporting artifacts help detect missing requirements, ignored findings, or unjustified drift, but do not become separate full review subjects. Earlier artifacts are evidence, not assumed truth.
review turns finish through one tool:
report_workflow_verdict { "verdict": "approve" | "feedback" | "reject", "summary": "One paragraph a human reads in the run timeline."}
Record findings as review_finding blocks first, then report the verdict. An end_turn on a review turn without this call fails the turn; the host cannot guess a verdict from prose.
Result summaries
Every successful turn should report a result:
report_result { "summary": "Fixed the retry accounting; two tests added; branch pushed."}
Use one or two non-technical sentences that tell the owner what was done or concluded and the outcome. The summary is validated at call time and preferred for the successful recap. Only Execute requires report_result for completion; every other mode falls back to the normal successful terminal summary when the call is omitted or fails, and Review, Plan, and Research still complete through their own verdict or artifact contracts. After request_input, stop without reporting a result or Review verdict.
The design rule: anything the model decides is a tool call; anything your agent code already knows (tokens, status, progress text) is an ACP event. Tool calls give model decisions schemas, validation errors, and retries. Events give mechanical facts a cheap streaming channel.
Visual artifacts
_meta["onehorizon.ai"].artifactsDir (also exported as ONE_WORKER_ARTIFACTS_DIR) names a writable directory for verification media: screenshots, screen recordings, rendered diffs. Files your agent leaves there are uploaded by the host after the turn and attached to the session, no tool call needed. Use it for evidence, not build output. Uploads accept images and video only, up to the size cap in limits and security.
Task interaction
The task's title, bounded description, and existing comments arrive as untrusted prompt content, not through a tool call. The same MCP server adds get_task_details for fetching the complete current task, get_parent_details for fetching the linked parent initiative when one exists, and list_task_comments for checking comments added since the turn started. All three take no task ID input: they always resolve to the turn's own task (and its parent) and stay inside the turn's workspace.
add_task_comment posts a comment on the current task, attributed to your agent, for discussion a person should read, such as a clarifying note or a decision and its reason. Progress and results go through report_result, and questions that block the turn go through request_input. The agent cannot edit or remove a posted comment. There is no tool for linking a pull request: the workspace's GitHub or GitLab integration creates and links the PR or MR once your agent pushes a branch.
Credentials and scope
The MCP token is minted per turn, scoped to the session's task, workflow run, and declared artifacts, and expires when the turn ends; limits and security lists the full scope rules. Tool calls that exceed the step's declared outputs fail with a descriptive error. Fix the call instead of retrying it.