Getting startedSet up integrationsCreate your first initiativeInvite your teamPlan today's workShare your first update
OverviewQuickstartRuntime manifestACP contractDocuments & toolsMCP toolsDistributeRun & monitorBuild cloud agentAgent sessionsReferenceLimits & securityTroubleshooting
DocsAPI Reference

Main

  • Home
  • About
  • Pricing
  • Vault
  • Changelog
  • Docs

Features

  • Roadmaps
  • Planning
  • Standups
  • Status updates
  • Insights
  • AI assistant / MCP
  • Integrations

Solutions

  • Startups
  • Dev shops / agencies
  • Software teams
  • Internal IT & platform teams

Alternatives

  • vs Jira
  • vs Linear
  • vs Asana
  • vs Monday.com
  • vs ClickUp
  • vs Notion

Company

  • Blog
  • Security
  • Log in
  • Sign up
  • Terms of Use
  • Privacy Policy

Resources

  • Docs
  • Community
  • API reference
  • CLI
  • Desktop app
  • SDK

© 2026 One Horizon. All rights reserved

FacebookInstagramThreadsXRedditTikTokYouTubeMedium


The ACP contract

The worker runtime is a headless Agent Client Protocol client; your runtime is an ACP agent. Everything on this page is standard ACP unless marked as a One Horizon behavior. The TypeScript and Python SDK helpers are optional: any ACP agent that implements this contract can run locally through the machine catalog in code, plan, research, or review mode.

Turn lifecycle

sequenceDiagram
  participant H as Worker runtime (ACP client)
  participant A as Your agent (ACP agent)
  H->>A: spawn process (manifest command)
  H->>A: initialize (capabilities)
  A->>H: capabilities (loadSession?, mcp transports)
  H->>A: session/new (cwd = task worktree, mcpServers = [One Horizon tools])
  A->>H: sessionId
  H->>A: session/prompt (content blocks, _meta context)
  A-->>H: session/update × n (messages, thoughts, plans, tool calls, usage)
  A->>H: stopReason
  H->>A: terminate — process exits
Sequence diagram
  • One process per turn. The host spawns your command, runs one session with one prompt turn, and terminates the process after the stop reason. If your agent advertises sessionCapabilities.resume or loadSession, the host uses it for multi-turn continuity (feedback loops, resume-after-input) instead of replaying context into a fresh session. Advertise it if you can; retries get cheaper.
  • Timeouts are the host's. A turn that exceeds the configured turn timeout, or emits nothing for the stall window, is cancelled (session/cancel) and the process terminated. Do not build your own watchdog; do keep updates flowing while you work.

What arrives in the prompt

session/prompt carries ordered content blocks:

  1. Trusted policy — platform instructions as an <instructions trust="trusted"> markdown block (AgentTrustedInstructionsV1): policy rules, workflow routing facts, agent/worker custom instructions. _meta["onehorizon.ai"].trust = "trusted".
  2. Workflow instructions — the step's operating instructions. Also trust = "trusted".
  3. Untrusted context — task title, description, comments, user prompt, resume input as a <context trust="untrusted"> markdown block (AgentTaskContextV1). trust = "untrusted".
  4. Resources — images or files referenced by the task, as standard resource blocks.

A vanilla ACP agent that ignores _meta still sees the blocks in the same order and framing built-in runtimes receive; that is a fully working configuration. An agent that reads the trust markers can do better: map trusted blocks to its system prompt and untrusted blocks to user content.

_meta["onehorizon.ai"] appears in two places, each a versioned, schema-validated shape — not free-form:

  • Per content block (on every text block in the prompt): trust, and taskMode on the untrusted block only. one runtime dev and the runtime conformance check add synthetic: true to this block on their generated turns; real turns never set it.
  • Once on session/new (and session/load/session/resume): a single comprehensive bundle — taskId, workspaceId, ownerUserId, sessionId, workflowRunId, workflowStepId, workflowBranch, attempt (the workflow step's server-owned pass number), runtimeAttempt (a separate worker-local counter for retries/resumes of this same session — crash recovery, provider retries — distinct from attempt), taskMode, artifactsDir, linkedDocumentIds, and labeled goals/products/skills ({ labelId, name } pairs). Every field is present on every turn — absent data is an explicit null, never a missing key — so a non-LLM agent can rely on the same shape whether or not the turn is workflow-linked. This is the only structured data channel available to an agent that doesn't parse prose; a plain scripted agent should read this instead of the prompt text.

Both shapes below are generated directly from the schema the worker runtime validates against before sending — they can't drift from what your agent actually receives.

Per-block _meta:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "version": {
      "type": "number",
      "const": 1
    },
    "trust": {
      "type": "string",
      "enum": [
        "trusted",
        "untrusted"
      ]
    },
    "taskMode": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "plan",
            "code",
            "review",
            "research"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "synthetic": {
      "type": "boolean"
    }
  },
  "required": [
    "version",
    "trust",
    "taskMode"
  ],
  "additionalProperties": false
}

Session-level _meta:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "version": {
      "type": "number",
      "const": 1
    },
    "taskId": {
      "type": "string"
    },
    "workspaceId": {
      "type": "string"
    },
    "ownerUserId": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "sessionId": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "workflowRunId": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "workflowStepId": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "workflowBranch": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "attempt": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ]
    },
    "runtimeAttempt": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ]
    },
    "taskMode": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "plan",
            "code",
            "review",
            "research"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "artifactsDir": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "linkedDocumentIds": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "goals": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "labelId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "labelId",
          "name"
        ],
        "additionalProperties": false
      }
    },
    "products": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "labelId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "labelId",
          "name"
        ],
        "additionalProperties": false
      }
    },
    "skills": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "labelId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "labelId",
          "name"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "version",
    "taskId",
    "workspaceId",
    "ownerUserId",
    "sessionId",
    "workflowRunId",
    "workflowStepId",
    "workflowBranch",
    "attempt",
    "runtimeAttempt",
    "taskMode",
    "artifactsDir",
    "linkedDocumentIds",
    "goals",
    "products",
    "skills"
  ],
  "additionalProperties": false
}

Trusted policy text block (<instructions trust="trusted">):

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "version": {
      "type": "number",
      "const": 1
    },
    "policyRules": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "workflowDocumentsGuidance": {
      "type": "string"
    },
    "workflowRun": {
      "type": "object",
      "properties": {
        "workflowRunId": {
          "type": "string"
        },
        "workflowStepId": {
          "type": "string"
        },
        "attemptNumber": {
          "type": "number"
        },
        "taskMode": {
          "type": "string",
          "enum": [
            "plan",
            "code",
            "review",
            "research"
          ]
        },
        "taskModeGuidance": {
          "type": "string"
        },
        "expectedInputsGuidance": {
          "type": "string"
        },
        "workflowBranch": {
          "type": "string"
        },
        "nextStep": {
          "type": "object",
          "properties": {
            "terminal": {
              "type": "boolean"
            },
            "nextStepId": {
              "type": "string"
            },
            "nextStepType": {
              "type": "string",
              "enum": [
                "agent",
                "human_gate",
                "unknown"
              ]
            },
            "guidance": {
              "type": "string"
            }
          },
          "required": [
            "terminal",
            "guidance"
          ],
          "additionalProperties": false
        },
        "finalReviewPassGuidance": {
          "type": "string"
        }
      },
      "required": [
        "workflowRunId",
        "workflowStepId",
        "attemptNumber",
        "taskModeGuidance"
      ],
      "additionalProperties": false
    },
    "agentCustomInstructions": {
      "type": "string"
    },
    "workerCustomInstructions": {
      "type": "string"
    }
  },
  "required": [
    "version",
    "policyRules"
  ],
  "additionalProperties": false
}

Untrusted task context text block (<context trust="untrusted">):

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "version": {
      "type": "number",
      "const": 1
    },
    "taskId": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "workspaceId": {
      "type": "string"
    },
    "providerName": {
      "type": "string"
    },
    "providerUseCase": {
      "type": "string"
    },
    "parentInitiative": {
      "type": "object",
      "properties": {
        "identifier": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "identifier"
      ],
      "additionalProperties": false
    },
    "goals": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "products": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "skills": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "comments": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/__schema0"
      }
    },
    "linkedDocuments": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "documentId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "requirement",
              "task",
              "design_doc",
              "spec",
              "research",
              "review",
              "notes"
            ]
          },
          "excerpt": {
            "type": "string"
          }
        },
        "required": [
          "documentId",
          "title",
          "type",
          "excerpt"
        ],
        "additionalProperties": false
      }
    },
    "sessionPrompt": {
      "type": "string"
    },
    "workflowHandoffNote": {
      "type": "string"
    }
  },
  "required": [
    "version",
    "taskId",
    "title",
    "comments",
    "linkedDocuments"
  ],
  "additionalProperties": false,
  "$defs": {
    "__schema0": {
      "type": "object",
      "properties": {
        "author": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ]
        },
        "content": {
          "type": "string"
        },
        "createdAt": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ]
        },
        "replies": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/__schema0"
          }
        }
      },
      "required": [
        "content",
        "replies"
      ],
      "additionalProperties": false
    }
  }
}

Trust boundaries

Untrusted blocks are task data, not instructions. Your agent must not let untrusted content override trusted policy, no matter how convincingly a task description asks. If your framework has a system/user message distinction, use it.

Headless behaviors

ACP grew up inside editors with a human present. The worker runtime has no human at the keyboard, so:

  • session/request_permission is answered immediately by host policy (the agent's configured permission mode). Never block waiting for richer interaction; if you need genuine human input, finish the turn — the platform's awaiting-input flow handles the round-trip and resumes you.
  • Client fs/terminal capabilities are not offered. You run in the task worktree with the user's OS permissions; use your own process's filesystem and shell access directly. cwd from session/new is the workspace boundary.
  • Unknown extension methods you send are answered per spec (-32601); unknown notifications are ignored.

What the host does with your updates

Your session/updateWhere it lands
agent_message_chunkLive activity on the task, sentence-buffered
agent_thought_chunkCollapsed reasoning in the session transcript
planThe plan panel on the run — keep it current
tool_call / tool_call_updateSession transcript detail
usage_updateContext size and cumulative cost on the dashboards. Per-turn token breakdowns appear when your agent emits them; dashboards degrade gracefully when it doesn't

Emit meaningfully, not constantly: updates are your only voice in the product, and silence past the stall window looks like a hang.

Outcome mapping

stopReasonSession outcome
end_turnSucceeded, unless the task mode required a verdict or artifact that never arrived (see below)
refusalAwaiting input: your stated reason is shown to the user as a question; when they clarify, the session resumes. Refusals are never auto-retried
max_tokens, max_turn_requestsFailed, retryable: the workflow's retry policy and pass accounting apply; repeated budget failures trigger the stall notification
cancelledWhatever the host requested (user cancel, timeout, shutdown)
Process exit without a stop reasonFailed, protocol violation logged with your stderr

Mode contracts (One Horizon behavior): plan turns must write the plan artifact and review turns must call report_workflow_verdict, both through the injected MCP tools described in documents and tools. An end_turn without the required tool call fails the turn with a hint in the session log. code turns have no required tool call: implement, commit locally, and preferably finish with report_result.

Conformance

one runtime dev validates all of the above on every local turn and prints violations inline. Before distributing, run every mode you declare in the manifest:

one runtime dev --mode codeone runtime dev --mode plan && one runtime dev --mode review   # if declared

Plan, research, and review routing unlock for a runtime only after that runtime declares the mode and passes conformance for it.


PreviousRuntime manifestNextDocuments & tools

MCP tools

Every MCP tool the worker runtime can register for a turn, generated straight from the runtime tool catalog.

Overview

Plug any ACP-compatible agent into the worker runtime. One Horizon handles auth, sessions, tools, and monitoring; you build the agent.

Runtime manifest

The one.json reference: everything the worker runtime needs to install, verify, and launch your agent.

Troubleshooting

Fix install, discovery, auth, protocol, git, and operations failures for custom runtimes, plus the cloud agent API lifecycle.

  • Turn lifecycle
  • What arrives in the prompt
  • Headless behaviors
  • What the host does with your updates
  • Outcome mapping
  • Conformance
  • Back to top