Semantic service

[ AxiomCore · Documentation ]

Semantic service protocol reference

The axiom-agent-semantic/v1 envelope, snapshots, the 17 operations with their params, results and errors, limits, and the apply and recovery rules.

acore-semantic speaks one protocol, axiom-agent-semantic/v1, over three transports: MCP (acore-semantic mcp), JSON lines (acore-semantic serve) and a one-shot command (acore-semantic --root <project> < request.json). The operations, fields and errors are the same on all three.

The protocol is defined by JSON Schema (draft 2020-12) files, published on this site (see Schema files). The tables marked as generated on this page are produced from those schemas and from the service's capability manifest.

Schema files

Each schema is a static file under https://docs.axiomcore.dev/semantic-service/schemas/. index.json lists every file with its URL, $id and title.

FileDefines
envelope.request.jsonEvery request: the envelope fields each operation takes
envelope.response.jsonEvery response, success or error
error.jsonThe error object and its code vocabulary
common.jsonIds, workspace and snapshot identity, node references, limits, truncation, coverage, diagnostics
edits.jsonEdit operations, edit options, id maps, relocations, candidates, checks
operations/<operation>.request.jsonThe params of one operation (linked from each operation below)
operations/<operation>.result.jsonThe result of one operation; x-errors lists its error codes

Each file's $id has the form https://schemas.axiomcore.dev/agent-semantic/v1/<file>. The $id is the schema's identifier, not a download location: nothing is served at schemas.axiomcore.dev. The files on this site are the authoritative, published copies. References between files are relative (for example ../common.json#/$defs/path from operations/), and a validator resolves them against the $id, not against the URL a file was downloaded from. A validator that fetches references on demand therefore tries schemas.axiomcore.dev and fails. To validate, either load all 39 schema files into your validator first, so it finds each one by its $id, or configure it to map https://schemas.axiomcore.dev/agent-semantic/v1/ to https://docs.axiomcore.dev/semantic-service/schemas/.

Conventions

  • Field names and enum values are snake_case. Readers ignore fields they do not know; the service rejects unknown fields inside edit operations and apply preconditions, because ignoring a precondition could apply an edit you did not intend.
  • Paths are relative to the project root with / separators, except workspace.open roots, which are absolute.
  • SHA-256 values are lowercase hex. Timestamps are RFC 3339 with an offset. Diagnostic line and column start at 1; lengths and columns count Unicode scalar values.
  • Over MCP each operation is a tool named with _ for . (node_find). The tool's arguments are the request envelope without protocol and operation; the server fills workspace. The tool result's structured content is the response envelope.

The examples on this page run in order against a project directory named task-app whose page is like the quick start example, with a query and a mutation of a backend contract tasks and a list of tasks. It also has the contract and the UI lock the Axiom CLI produces, so it shows the contract fields. Ids, versions and digests from your own project differ.

task-app/main.acore, used by the examples on this page
module tasks.app.ui

use contract Tasks from "tasks" audience "mobile"

app TasksApp { route "/" => Home }

page Home {
  state draft: String = ""
  query tasks = Tasks.list_tasks()
  mutation create = Tasks.create_task(title: draft)

  action submit() {
    create.run()
    draft = ""
  }

  view {
    View {
      Input(value: draft, placeholder: "Add a task")
      Button(label: "Add", on_press: submit)

      if tasks.pending { Text("Loading...") }
      else if tasks.error { Text("Could not load tasks") }
      else { List(items: tasks.data, key: |task| task.id, list_type: "single", span_count: 1, scroll_orientation: "vertical") { task => Text(task.title) } }
    }
  }
}

Values in angle brackets, such as <workspace>, stand for ids from earlier responses. In responses, … marks text left out, including the end of long hashes.

Request envelope

A request
{
  "protocol": "axiom-agent-semantic/v1",
  "operation": "node.find",
  "workspace": "<workspace>",
  "snapshot": "latest",
  "limits": {"max_bytes": 65536},
  "params": {"query": "Add", "limit": 10}
}
FieldRequiredTypeMeaning
protocolyes"axiom-agent-semantic/v1"Always this value.
operationyescapabilities, workspace.open, project.overview, node.find, node.get, node.edits, graph.query, context.build, impact.analyze, changes.since, node.relocate, change.propose, change.inspect, check.run, change.apply, change.discard, edit.planEvery operation of v1. The capability manifest says which are implemented.
workspacenostring (at most 256 characters)Opaque workspace handle returned by workspace.open. Scoped to the host process and caller.
snapshotnostring (at most 256 characters)Read operations: the snapshot to read (id or latest).
base_snapshotnostring (at most 256 characters)change.propose and edit.plan: the snapshot the edits are written against. Must be an id, not latest.
request_idnostring (at most 128 characters)Caller-chosen idempotency key, scoped to workspace and caller. Bound to the request's input fingerprint.
limitsnoobject (limits)Request limits. Omitted fields take the defaults the capability manifest lists. Bytes are authoritative; tokens are never a request limit.
paramsyesobjectOperation arguments; schemas/operations/<operation>.request.json.

request_id is an idempotency key: the same request_id with the same input returns the recorded result with replayed: true, and the same request_id with different input is conflict (request_id_reused). Only edit and apply operations record it; elsewhere it is echoed.

Which envelope fields each operation takes:

Operationworkspacesnapshotbase_snapshotrequest_id
capabilitiesnot allowednot allowednot allowednot allowed
workspace.opennot allowedoptionalnot allowednot allowed
project.overviewrequiredrequirednot allowedoptional
node.findrequiredrequirednot allowedoptional
node.getrequiredrequirednot allowedoptional
node.editsrequiredrequirednot allowedoptional
graph.queryrequiredrequirednot allowedoptional
context.buildrequiredrequirednot allowedoptional
impact.analyzerequiredrequirednot allowedoptional
changes.sincerequiredrequirednot allowedoptional
node.relocaterequiredrequirednot allowedoptional
change.proposerequirednot allowedrequiredrequired
change.inspectrequirednot allowednot allowedoptional
check.runrequiredrequired unless params.candidate is givennot allowedoptional
change.applyrequirednot allowednot allowedrequired
change.discardrequirednot allowednot allowedoptional
edit.planrequirednot allowedrequirednot allowed

Response envelope

Every response, success or error, has these fields, and exactly one of result and error:

FieldMeaning
protocol, operationoperation echoes the request.
request_idPresent when the request had one.
workspaceThe workspace id, or null for capabilities and errors raised before a workspace was resolved.
snapshotThe snapshot the answer describes (for an edit, its base; for a candidate, the candidate's snapshot with overlay set), or null. See Snapshots.
toolchainCompiler version and identity, edit rules identity, language_profile and target.
coveragecompleteness (complete, partial or unknown), exhaustive, and gaps, each with a reason. An empty answer proves absence only when exhaustive is true.
truncationtruncated, the limits applied, bytes used, omissions (each with a reason, a count, up to 50 omitted node ids and expansion refs) and a continuation cursor or null.
resultThe operation's result.
errorThe error object.

A response never silently drops content. When a limit cuts an answer, truncation.truncated is true and omissions say what was left out. max_bytes counts the UTF-8 bytes of the compact JSON of result.

Snapshots and workspaces

A workspace is one attached project root. workspace.open returns its id; every later request except capabilities names it. The service serves one root per process: the --root it was started with.

A snapshot is an immutable capture of the project's sources and inputs (contracts and lock) under one compiler, language profile and target. Its id is derived from its content. latest captures the files on disk now; the response names the snapshot it used, so you can keep reading that exact state. A snapshot's semantic_state says how far compilation got:

  • syntax: parsed only
  • resolved: names resolved, not validated
  • validated: compiled without errors
  • unavailable: not even parsed

In this build unavailable means there is no node graph, which is not always a parse failure: a project whose source parses but that lacks its UI lock is also reported as unavailable (with status needs_preparation). On an unavailable snapshot, node.find answers compile_failed, node.edits answers compile_failed (not_validated), and project.overview still returns the diagnostics.

A read on a syntax or resolved snapshot is partial with a broken_source gap. Edits need a validated base, except bounded repairs: an edit on a broken base is accepted when it leaves fewer errors and none outside the declarations it changed.

When a file changes on disk after a snapshot was captured, reads of that snapshot still describe the captured state and add snapshot.disk.state: changed with the changed paths. Read latest for the current files.

A node id names a node within one snapshot, for example element:Home/view/0/1. Do not build or parse ids. To follow nodes to a newer snapshot, use an edit's id_map, changes.since or node.relocate. Every node carries a version, a fingerprint of its kind, name, file and authored text; pass it as expected_node_version to refuse an edit if the node changed.

A candidate is a proposed change: your operations applied to a private copy of the base snapshot and compiled. It has an id and a version (1 when created, increased each time you extend it) and is open, applied or discarded. Only change.apply writes it to the project.

Operations

The 17 operations, in the order a client usually needs them. Each section lists the params and result fields generated from the schemas, then a real request and response.

capabilities

The manifest of what this service serves: each operation and edit kind with its status (implemented, partial or planned), profiles, checks, limits, publication guarantees and error codes. Call it first, and use only what it lists. It needs no workspace. acore-semantic --capabilities prints the same manifest, plus toolchain, without a request (see the quick start).

Params (schemas/operations/capabilities.request.json)

FieldRequiredTypeMeaning
profilesnoarray of string (at most 64 characters)Restrict the manifest to these language profiles.

Result (schemas/operations/capabilities.result.json)

FieldRequiredTypeMeaning
manifestyesobjectThe capability manifest: what this build serves.
manifest_fingerprintyesstringLowercase hex SHA-256 over a documented canonical input (node version, option fingerprint, input fingerprint).

manifest fields:

FieldRequiredTypeMeaning
protocolyesobjectProtocol name, status (frozen) and the frozen operations.
serviceyesobjectService name and version.
operationsyesarray of objectEvery operation with its status (implemented, partial or planned) and the version that first served it.
edit_kindsyesarray of objectEvery edit family with its status.
profilesyesarray of objectSupported language profiles, each with its status and targets.
limitsyesobjectRequest limit defaults and maximums, and the service bounds (see Limits).
checksnoarray of objectChecks that check.run and change.apply accept, with their status.
publicationyesarray of objectPublication profiles (local_filesystem) with their status and guarantees.
error_codesyesarray of unsupported_operation, invalid_arguments, ambiguous_owner, read_only_origin, stale_snapshot, precondition_failed, compile_failed, conflict, insufficient_context, snapshot_expired, permission_denied, resource_limit, not_found, internalThe error codes this build can return.
external_writesnoobjectHow the service detects writes by editors and tools it does not coordinate (external writers).

Error codes: internal, unsupported_operation, invalid_arguments, resource_limit.

Request: capabilities
{"protocol": "axiom-agent-semantic/v1", "operation": "capabilities", "params": {}}
Response (excerpt)
{
  "workspace": null,
  "result": {
    "manifest": {
      "edit_kinds": [
        {
          "kind": "set_property",
          "status": "implemented",
          …
        },
        {
          "kind": "bind_property",
          "status": "implemented",
          …
        },
        …
      ],
      "operations": [
        {
          "name": "capabilities",
          "status": "implemented",
          …
        },
        {
          "name": "workspace.open",
          "status": "partial",
          …
        },
        {
          "name": "project.overview",
          "status": "implemented",
          …
        },
        …
      ],
      "protocol": {
        "name": "axiom-agent-semantic/v1",
        "status": "frozen",
        …
      },
      "service": {
        "name": "acore-semantic",
        "version": "0.1.4"
      },
      …
    },
    …
  },
  …
}

workspace.open

Attaches the project root and captures a snapshot. Each project reports a status: ready, needs_preparation (with preparation steps for you to run with the Axiom CLI) or unsupported. The result also includes the manifest. It never installs, extracts or runs anything.

Params (schemas/operations/workspace.open.request.json)

FieldRequiredTypeMeaning
rootsyesarray of object, 1 to 16 itemsThe project root, as {path} with an absolute path (entry may only be main.acore). This build accepts exactly one root, the one the process was started with.
language_profilenostring (at most 64 characters)Language profile to open the project with. Only acore-ui is served; another value reports the project as unsupported.
targetnostring (at most 64 characters)Target to compile for. Only web is served; another value reports the project as unsupported.

Result (schemas/operations/workspace.open.result.json)

FieldRequiredTypeMeaning
workspaceyesobjectThe workspace: its id, its roots and where sources come from.
projectsyesarray of object, 1 to any itemsOne entry per project: id (the root directory's name), entry, profile, target, status (ready, needs_preparation or unsupported), preparation steps and diagnostic counts.
capabilitiesyesobject (manifest)The capability manifest, as capabilities returns it.

workspace fields:

FieldRequiredTypeMeaning
idyesstring (at most 256 characters)Opaque workspace handle returned by workspace.open. Scoped to the host process and caller.
rootsyesarray of object, 1 to any itemsEach root with its root_id and canonical absolute path.
source_authorityyeslocal_filesystemWhere sources are read from: always the local filesystem.

capabilities fields:

FieldRequiredTypeMeaning
protocolyesobjectProtocol name, status (frozen) and the frozen operations.
serviceyesobjectService name and version.
operationsyesarray of objectEvery operation with its status (implemented, partial or planned) and the version that first served it.
edit_kindsyesarray of objectEvery edit family with its status.
profilesyesarray of objectSupported language profiles, each with its status and targets.
limitsyesobjectRequest limit defaults and maximums, and the service bounds (see Limits).
checksnoarray of objectChecks that check.run and change.apply accept, with their status.
publicationyesarray of objectPublication profiles (local_filesystem) with their status and guarantees.
error_codesyesarray of unsupported_operation, invalid_arguments, ambiguous_owner, read_only_origin, stale_snapshot, precondition_failed, compile_failed, conflict, insufficient_context, snapshot_expired, permission_denied, resource_limit, not_found, internalThe error codes this build can return.
external_writesnoobjectHow the service detects writes by editors and tools it does not coordinate (external writers).

Error codes: invalid_arguments, not_found, permission_denied, resource_limit, internal, unsupported_operation, compile_failed.

Request: workspace.open
{"protocol": "axiom-agent-semantic/v1", "operation": "workspace.open", "snapshot": "latest",
 "params": {"roots": [{"path": "<project-path>"}]}}
Response (excerpt)
{
  "operation": "workspace.open",
  "workspace": "ws-…",
  "snapshot": {
    "id": "snap-8d409ade6cc9…",
    "semantic_state": "validated",
    …
  },
  "result": {
    "projects": [
      {
        "project_id": "task-app",
        "semantic_state": "validated",
        "status": "ready",
        …
      }
    ],
    "workspace": {
      "id": "ws-…",
      "source_authority": "local_filesystem",
      …
    },
    …
  },
  …
}

project.overview

Modules with their owners (pages and components), imports and diagnostic counts, entry points, imported contracts and diagnostics. Every list is paged by limits.max_items; pass truncation.continuation back as params.cursor for the next page. The cursor stays on the same snapshot.

Params (schemas/operations/project.overview.request.json)

FieldRequiredTypeMeaning
projectsnoarray of string (at most 128 characters)Project ids to describe. Default: every project in the workspace (this build has one).
includenoarray of modules, entry_points, contracts, diagnosticsWhich lists to return. Default: all four.
cursornostring (at most 1024 characters)Opaque continuation token bound to one snapshot and one request shape. Valid until the snapshot expires.

Result (schemas/operations/project.overview.result.json)

FieldRequiredTypeMeaning
projectsyesarray of objectEach project with its entry, profile, target, semantic state and diagnostic counts.
modulesyesarray of objectEach module (source file) with its owners (pages and components), imports and error and warning counts.
entry_pointsyesarray of object (nodeSummary)The pages the app's routes name, in route order.
contractsyesarray of objectImported backend contracts: name, artifact path and SHA-256.
diagnosticsyesarray of object, 0 to 200 items (diagnostics)Compiler diagnostics, at most 200.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot.

Request: project.overview
{"protocol": "axiom-agent-semantic/v1", "operation": "project.overview", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "params": {"include": ["entry_points", "contracts"]}}
Response (excerpt)
{
  "snapshot": {
    "id": "snap-8d409ade6cc9…",
    …
  },
  "truncation": {
    "truncated": false,
    …
  },
  "result": {
    "contracts": [
      {
        "name": "Tasks",
        "node": "contract_import:Tasks",
        "path": ".axiom/dev/contracts/tasks.axiom",
        "sha256": "52cd75a52c98…"
      }
    ],
    "diagnostics": [],
    "entry_points": [
      {
        "id": "page:Home",
        "kind": "page",
        "name": "Home",
        "path": "main.acore",
        "version": "7dd07ff0bbad…"
      }
    ],
    "modules": [],
    "projects": [
      {
        "diagnostic_counts": {
          "errors": 0,
          "warnings": 1
        },
        "entry": "main.acore",
        "language_profile": "acore-ui",
        "project_id": "task-app",
        "semantic_state": "validated",
        "target": "web"
      }
    ]
  },
  …
}

node.find

Finds nodes by a case-insensitive substring of their name, id or a string literal property value, with optional kind, owner and path filters. Results are in document order, not ranked. More matches than limit are reported as an omission: narrow the query.

Params (schemas/operations/node.find.request.json)

FieldRequiredTypeMeaning
queryyesstring (at most 200 characters)Trimmed, case-insensitive substring of name, id, or a string-literal property value. Empty matches every node.
kindnostring (at most 64 characters)Exact kind filter; an unknown kind matches nothing.
ownernostring (at most 1024 characters)Only nodes owned (transitively) by this page or component.
pathnostring (at most 1024 characters)Only nodes whose authored declaration is in this file.
limityesinteger (1..50)Maximum number of nodes to return (1 to 50). More matches are reported as an omission; narrow the query.

Result (schemas/operations/node.find.result.json)

FieldRequiredTypeMeaning
nodesyesarray of object (nodeSummary)Matching nodes, each with id, kind, name, file and version.
matchesnoarray of objectOne entry per node, same order: why it matched.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot, compile_failed.

Request: node.find
{"protocol": "axiom-agent-semantic/v1", "operation": "node.find", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "params": {"query": "Add", "kind": "element", "limit": 10}}
Response (excerpt)
{
  "coverage": {
    "completeness": "complete",
    "exhaustive": true,
    "gaps": []
  },
  "result": {
    "matches": [
      {
        "node": "element:Home/view/0/0",
        "reasons": [
          "property_value"
        ]
      },
      {
        "node": "element:Home/view/0/1",
        "reasons": [
          "property_value"
        ]
      }
    ],
    "nodes": [
      {
        "id": "element:Home/view/0/0",
        "kind": "element",
        "name": "Input",
        "path": "main.acore",
        "version": "47220ffb7c58…"
      },
      {
        "id": "element:Home/view/0/1",
        "kind": "element",
        "name": "Button",
        "path": "main.acore",
        "version": "24495d3190bd…"
      }
    ]
  },
  …
}

node.get

Properties, edges, source and an edit summary for up to 50 node ids. projection (summary, standard, full) and include choose the parts. Over max_bytes, optional parts are dropped and listed as an omission with expansion refs.

Params (schemas/operations/node.get.request.json)

FieldRequiredTypeMeaning
nodesyesarray of string (at most 1024 characters), 1 to 50 itemsNode ids to read (1 to 50).
projectionnosummary, standard, fullPreset. summary: node only. standard (default): properties and edges. full: also body and provenance.
includenoarray of properties, edges, incoming, body, provenance, editsAdds to the preset.
limitnointeger (1..200)Caps properties and edges per node independently.

Result (schemas/operations/node.get.result.json)

FieldRequiredTypeMeaning
nodesyesarray of objectOne entry per requested id: the node with the parts requested (properties, edges, body, provenance, edit summary).

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot, compile_failed.

Request: node.get
{"protocol": "axiom-agent-semantic/v1", "operation": "node.get", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "params": {"nodes": ["element:Home/view/0/1"]}}
Response (excerpt)
{
  "result": {
    "nodes": [
      {
        "edges": [
          {
            "direction": "outgoing",
            "kind": "child_of",
            "layer": "declared",
            "node": "element:Home/view/0"
          },
          {
            "direction": "outgoing",
            "kind": "triggers",
            "layer": "resolved",
            "node": "action:Home.submit"
          }
        ],
        "node": {
          "id": "element:Home/view/0/1",
          "kind": "element",
          "name": "Button",
          "path": "main.acore",
          "version": "24495d3190bd…"
        },
        "properties": [
          {
            "editable": true,
            "name": "label",
            "type": "String",
            "value": "Add"
          },
          {
            "editable": false,
            "name": "on_press",
            "type": "Action",
            "value": "submit"
          }
        ]
      }
    ]
  },
  …
}

node.edits

The edits each node accepts now. Every option has an option_id and a fingerprint bound to the snapshot, the node version and the edit rules; cite it in change.propose as option and a stale option is refused. An edit that is not offered is not legal; include_unavailable: true lists what is not offered.

Params (schemas/operations/node.edits.request.json)

FieldRequiredTypeMeaning
nodesyesarray of string (at most 1024 characters), 1 to 20 itemsNode ids to ask about (1 to 20).
kindsnoarray of set_property, bind_property, list_element, declaration, set_reference, import, replace_regionOnly list options of these edit families. Default: every family.
include_unavailablenobooleanAlso list the edit families that are not offered for the node. The service does not say why.

Result (schemas/operations/node.edits.result.json)

FieldRequiredTypeMeaning
nodesyesarray of objectPer node: its id, node_version, the legal options (each with option_id and fingerprint) and, if asked, the families not offered.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot, compile_failed.

Request: node.edits
{"protocol": "axiom-agent-semantic/v1", "operation": "node.edits", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "params": {"nodes": ["element:Home/view/0/1"], "include_unavailable": true}}
Response (excerpt)
{
  "result": {
    "nodes": [
      {
        "node": "element:Home/view/0/1",
        "node_version": "24495d3190bd…",
        "options": [
          {
            "accepts": "String",
            "fingerprint": "8433d5033595…",
            "kind": "set_property",
            "option_id": "o1",
            "property": "label"
          },
          {
            "accepts": "String",
            "fingerprint": "0777d73f1904…",
            "kind": "bind_property",
            "option_id": "o2",
            "property": "label",
            "states": [
              "state:Home.draft"
            ]
          },
          {
            "accepts": "Element",
            "fingerprint": "b35723f8087a…",
            "kind": "list_element",
            "ops": [
              "remove",
              "insert"
            ],
            "option_id": "o3",
            "text": "Button(label: \"Add\", on_press: submit)"
          }
        ],
        "unavailable": [
          {
            "code": "unsupported_operation",
            "kind": "declaration",
            "reason": "declaration is not offered for this node; acore does not report why"
          },
          {
            "code": "unsupported_operation",
            "kind": "set_reference",
            "reason": "set_reference is not offered for this node; acore does not report why"
          },
          {
            "code": "unsupported_operation",
            "kind": "import",
            "reason": "import is not offered for this node; acore does not report why"
          }
        ]
      }
    ]
  },
  …
}

graph.query

Relationships from compiler facts: dependencies (outgoing), dependents (incoming), references (incoming use sites) or paths (from from to to). Each edge has a kind (reads, writes, triggers and others), a layer (declared or resolved) and a source site. Edges to code the compiler cannot see, such as foreign extension actions, are reported as boundaries with partial coverage.

Params (schemas/operations/graph.query.request.json)

FieldRequiredTypeMeaning
fromyesarray of string (at most 1024 characters), 1 to 20 itemsStart node ids (1 to 20).
modeyesdependencies, dependents, references, pathsdependencies: outgoing; dependents: incoming; references: incoming use sites; paths: connecting paths from -> to.
tonoarray of string (at most 1024 characters), 1 to 20 itemsFor mode: paths: the end node ids (1 to 20).
edge_kindsnoarray of stringRestrict to these relations. Omitted: the profile's default dependency relations, disclosed in result.traversed.
layersnoarray of declared, resolved, observedFact layers to follow. This build has declared and resolved facts only.
transitivenobooleanFollow relationships beyond the first step, up to limits.max_depth.

Result (schemas/operations/graph.query.result.json)

FieldRequiredTypeMeaning
traversedyesobjectWhat was followed: direction, edge kinds and layers.
nodesyesarray of object (nodeSummary)Summaries of the nodes the answer mentions.
edgesyesarray of objectEach relationship found: from, kind, to, layer, depth and source site.
pathsnoarray of objectFor mode: paths: each path as a list of node ids.
boundariesyesarray of objectWhere the walk met something it cannot see through (foreign implementation, unresolved reference). Not an empty dependency set.

traversed fields:

FieldRequiredTypeMeaning
directionyesoutgoing, incoming, bothoutgoing, incoming or both.
edge_kindsyesarray of stringEdge kinds that were followed.
layersyesarray of declared, resolved, observedFact layers that were followed.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot, compile_failed.

Request: graph.query
{"protocol": "axiom-agent-semantic/v1", "operation": "graph.query", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "params": {"from": ["state:Home.draft"], "mode": "dependents"}}
Response (excerpt)
{
  "result": {
    "edges": [
      {
        "depth": 1,
        "from": "mutation:Home.create",
        "kind": "reads",
        "layer": "resolved",
        "site": {
          "column": 12,
          "line": 10,
          "path": "main.acore"
        },
        "to": "state:Home.draft"
      },
      {
        "depth": 1,
        "from": "element:Home/view/0/0",
        "kind": "reads",
        "layer": "resolved",
        "site": {
          "column": 7,
          "line": 19,
          "path": "main.acore"
        },
        "to": "state:Home.draft"
      },
      …
    ],
    "traversed": {
      "direction": "incoming",
      "edge_kinds": [
        "reads",
        "writes",
        "triggers",
        "calls",
        "invokes",
        "navigates_to"
      ],
      "layers": [
        "declared",
        "resolved"
      ]
    },
    …
  },
  …
}

context.build

A bounded slice of the project for a task. purpose selects a fixed recipe (understand, change_input, change_behavior, diagnose); each item says why it is included and whether it is required. Required context is never cut: if it does not fit in max_bytes the answer is insufficient_context with the bytes it needs and refs you can pass in expand.

Params (schemas/operations/context.build.request.json)

FieldRequiredTypeMeaning
focusyesarray of string (at most 1024 characters), 1 to 20 itemsNode ids the task is about (1 to 20).
purposeyesunderstand, change_input, change_behavior, change_schema, diagnoseThe recipe that chooses what to include. change_schema needs a backend profile and answers unsupported_operation in this profile.
includenoarray of signature, implementation, input_constraints, callers, consumers, authorization, diagnostics, testsKinds of context to add. tests and authorization produce coverage gaps in this profile.
expandnoarray of string (at most 512 characters), 0 to 50 itemsExpansionRef.ref values from an earlier response on the same snapshot.

Result (schemas/operations/context.build.result.json)

FieldRequiredTypeMeaning
itemsyesarray of objectEach included node with its depth from the focus, whether it is required, and why it is included.
edgesyesarray of objectRelationships between the included nodes.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot, compile_failed, insufficient_context.

Request: context.build
{"protocol": "axiom-agent-semantic/v1", "operation": "context.build", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "limits": {"max_bytes": 4096},
 "params": {"focus": ["element:Home/view/0/1"], "purpose": "change_input"}}
Response (excerpt)
{
  "truncation": {
    "truncated": false,
    "used": {
      "bytes": 1693
    },
    …
  },
  "result": {
    "items": [
      {
        "node": {
          "id": "element:Home/view/0/1",
          …
        },
        "reasons": [
          {
            "kind": "focus",
            "text": "element:Home/view/0/1: focus of change_input"
          }
        ],
        "required": true,
        "signature": "Button(label: \"Add\", on_press: submit)",
        …
      },
      {
        "node": {
          "id": "action:Home.submit",
          …
        },
        "reasons": [
          {
            "kind": "signature",
            "text": "action:Home.submit: element:Home/view/0/1 triggers it",
            "via": "element:Home/view/0/1"
          }
        ],
        "required": false,
        "signature": "submit()",
        …
      },
      …
    ],
    …
  },
  …
}

With a limit smaller than the required context:

Request: context.build over the limit
{"protocol": "axiom-agent-semantic/v1", "operation": "context.build", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "limits": {"max_bytes": 256},
 "params": {"focus": ["page:Home"], "purpose": "understand"}}
Response (excerpt)
{
  "error": {
    "code": "insufficient_context",
    "message": "the required context of understand on page:Home is 294 bytes, more than limits.max_bytes (256); it is never cut. Repeat with limits.max_bytes of at least 294 (and max_nodes of at least 1), a narrower include, or fewer focus nodes",
    "target": {
      "nodes": [
        "page:Home"
      ]
    },
    "diagnostics": [],
    "retryable": "none",
    "next_actions": [
      {
        "operation": "context.build",
        "reason": "Repeat with limits.max_bytes of at least details.required_bytes, or a narrower include"
      }
    ],
    "details": {
      "expand": [
        {
          "estimated_bytes": 272,
          "kind": "node",
          "node": "page:Home",
          "reason": "the item page:Home (required context); pass this ref in params.expand to include it as required",
          "ref": "ctx1:8d409ade6cc951e0:node:page:Home"
        }
      ],
      "required_bytes": 294,
      "required_items": 1
    }
  },
  …
}

impact.analyze

Everything that depends on the targets, transitively up to limits.max_depth levels, with the edge that links each impacted node.

Params (schemas/operations/impact.analyze.request.json)

FieldRequiredTypeMeaning
targetsyesarray of string (at most 1024 characters), 1 to 20 itemsNode ids to analyse (1 to 20).
directionyesdependents, dependencies, bothdependents (what a change would affect), dependencies, or both.
edge_kindsnoarray of stringOnly follow these edge kinds. Default: all.

Result (schemas/operations/impact.analyze.result.json)

FieldRequiredTypeMeaning
impactedyesarray of objectEach affected node with its depth, the node it was reached from, the edge kind and the layer.
testsnoarray of objectTest associations. Not returned by this build (no test associations in this profile).

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot, compile_failed.

Request: impact.analyze
{"protocol": "axiom-agent-semantic/v1", "operation": "impact.analyze", "workspace": "<workspace>",
 "snapshot": "<snapshot>", "params": {"targets": ["state:Home.draft"], "direction": "dependents"}}
Response (excerpt)
{
  "result": {
    "impacted": [
      {
        "depth": 1,
        "edge_kind": "reads",
        "from": "state:Home.draft",
        "node": {
          "id": "mutation:Home.create",
          …
        },
        …
      },
      {
        "depth": 1,
        "edge_kind": "reads",
        "from": "state:Home.draft",
        "node": {
          "id": "element:Home/view/0/0",
          …
        },
        …
      },
      {
        "depth": 1,
        "edge_kind": "writes",
        "from": "state:Home.draft",
        "node": {
          "id": "action:Home.submit",
          …
        },
        …
      },
      {
        "depth": 2,
        "edge_kind": "triggers",
        "from": "action:Home.submit",
        "node": {
          "id": "element:Home/view/0/1",
          …
        },
        …
      }
    ]
  },
  …
}

edit.plan

A dry run of change.propose: the same operations, checked by the same rules, returning the owners, files and required checks. It stores nothing and takes no request_id.

Params (schemas/operations/edit.plan.request.json)

FieldRequiredTypeMeaning
operationsyesarray of object or object or object or object or object or object or object or object or object or object or object, 1 to 50 itemsEdit operations (1 to 50), as for change.propose.

Result (schemas/operations/edit.plan.result.json)

FieldRequiredTypeMeaning
outcomeyessupported, required_but_missing, unsupportedsupported; unsupported when an operation is refused as not offered (see reason); required_but_missing when the batch needs an edit family this build does not implement.
reasonnostring (at most 2000 characters)Why the outcome is not supported.
ownersyesarray of objectPages and components the batch changes, with their files.
operationsyesarray of objectPer operation: index, kind, file and outcome.
id_mapnoarray of object (idMap)Optional: the id_map change.propose would return, composed over the batch from base_snapshot; present when the outcome is supported.
filesyesarray of string (at most 1024 characters)Files the batch would change.
required_checksnoarray of string (at most 64 characters)Checks a candidate of this batch would need to pass.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, stale_snapshot, snapshot_expired, precondition_failed, ambiguous_owner, read_only_origin, compile_failed.

Request: edit.plan
{"protocol": "axiom-agent-semantic/v1", "operation": "edit.plan", "workspace": "<workspace>",
 "base_snapshot": "<snapshot>",
 "params": {"operations": [{"kind": "set_property", "node": "element:Home/view/0/1", "property": "label",
   "old_value": "Add", "new_value": "Add task"}]}}
Response (excerpt)
{
  "result": {
    "files": [
      "main.acore"
    ],
    "id_map": [],
    "operations": [
      {
        "index": 0,
        "kind": "set_property",
        "node": "element:Home/view/0/1",
        "outcome": "supported",
        "path": "main.acore",
        "property": "label"
      }
    ],
    "outcome": "supported",
    "owners": [
      {
        "kind": "page",
        "node": "page:Home",
        "path": "main.acore"
      }
    ],
    "required_checks": [
      "compile"
    ]
  },
  …
}

change.propose

Applies 1 to 50 edit operations, in order, to a private copy of base_snapshot, compiles the result and returns a candidate. The batch is all or nothing: each operation sees the result of the ones before it, only the final state must compile, and on failure nothing is created and operation_index names the operation. An operation can name what it creates with handle, and a later operation refers to it as {"handle": "<name>"}. To extend an open candidate, pass candidate and expected_candidate_version.

Params (schemas/operations/change.propose.request.json)

FieldRequiredTypeMeaning
candidatenostring (at most 256 characters)Extend this open candidate instead of starting one. Its base must equal base_snapshot.
expected_candidate_versionnointeger (1..)Required with candidate.
operationsyesarray of object or object or object or object or object or object or object or object or object or object or object, 1 to 50 itemsEdit operations (1 to 50), applied in order, all or nothing. Each kind of operation is described after the error codes of this section.
checksnoarray of string (at most 64 characters)Checks to run on the final candidate before returning; compile always runs.

Result (schemas/operations/change.propose.result.json)

FieldRequiredTypeMeaning
candidateyesobject (candidate)The candidate: id, version, state, base snapshot, candidate snapshot, request_id and input fingerprint.
replayedyesbooleantrue when this answer is the recorded result of an earlier identical request.
operationsyesarray of object (operationOutcome), 1 to any itemsPer operation: index, kind, outcome, created node and its own id_map.
id_mapyesarray of object (idMap)Composed over the batch, from base_snapshot (or the previous candidate version) to this version.
filesyesarray of object (fileChange), 1 to any itemsFiles the candidate changes, with SHA-256 before and after.
diagnosticsyesarray of object, 0 to 200 items (diagnostics)Diagnostics of the candidate's compile, at most 200.
checksyesarray of object (checkResult), 1 to any itemsResult of each check run on the candidate.
evidenceyesobject (evidence)Evidence of a compile. (compiler_identity, target, sources, dependencies_fingerprint) is the reuse key of a check.
impactnoobjectNodes the change affects.
repairnoobject (repairOutcome)Present when the base is not validated (syntax or resolved): the accepted repair's base and result states and error counts.

candidate fields:

FieldRequiredTypeMeaning
idyesstring (at most 256 characters)Opaque id of a private candidate (change.propose).
versionyesinteger (1..)Increases with every successful change.propose on the candidate.
stateyesopen, applied, discarded, expiredThe candidate's state: open, applied, discarded or expired.
base_snapshotyesstring (at most 256 characters)Opaque id of one immutable captured snapshot. Never the reserved word latest.
snapshotyesstring (at most 256 characters)Snapshot id of base plus overlay; readable by the owning caller.
request_idyesstring (at most 128 characters)The request_id of the change.propose that produced this version.
input_fingerprintyesstringLowercase hex SHA-256 over a documented canonical input (node version, option fingerprint, input fingerprint).
expires_atnostringRFC 3339 with an explicit offset, uppercase T and Z.

evidence fields:

FieldRequiredTypeMeaning
toolchainyesobject (toolchain)The compiler identity the candidate was checked with.
inputsyesobjectThe inputs the compile read, with their digests.

impact fields:

FieldRequiredTypeMeaning
nodesyesarray of string (at most 1024 characters), 0 to 200 itemsAffected node ids, at most 200.
morenobooleantrue when more nodes are affected than listed.

repair fields:

FieldRequiredTypeMeaning
base_stateyessyntax, resolved, validated, unavailableHow far the snapshot got: syntax (parsed only), resolved (names resolved, not validated), validated (compiled without errors), unavailable (not even parsed).
base_errorsyesinteger (0..)Number of error diagnostics in the base snapshot.
result_stateyessyntax, resolved, validated, unavailableHow far the snapshot got: syntax (parsed only), resolved (names resolved, not validated), validated (compiled without errors), unavailable (not even parsed).
result_errorsyesinteger (0..)Number of error diagnostics after the repair.
touchedyesarray of string (at most 1024 characters), 0 to 50 itemsDeclarations the candidate changed, as <path>: <kind> <name>.
regressednoarray of string (at most 1024 characters), 0 to 50 itemsIn a refusal's details only: declarations that gained errors outside the broken ones the candidate changed.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, stale_snapshot, snapshot_expired, precondition_failed, ambiguous_owner, read_only_origin, compile_failed, conflict.

The edit operations (generated from edits.json). Every operation carries an exact precondition, old_value or old_text, copied from node.get or node.edits:

set_property: Set one authored literal scalar.

FieldRequiredTypeMeaning
kindyes"set_property"Always this value.
nodeyesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
propertyyesstring (at most 256 characters)Name of the property to set, as node.edits lists it.
old_valueyesany JSON valueExact precondition, as node.get returned it.
new_valueyesany JSON valueAny JSON value, including null.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

bind_property: Bind one authored property to a state of the same owner.

FieldRequiredTypeMeaning
kindyes"bind_property"Always this value.
nodeyesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
propertyyesstring (at most 256 characters)Name of the property to bind.
old_valueyesany JSON valueAny JSON value, including null.
targetyesstring (at most 1024 characters) or objectA state node of the element's owner.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

list_element, op: remove: Remove one element or conditional from a view children list.

FieldRequiredTypeMeaning
kindyes"list_element"Always this value.
opyes"remove"Always this value.
nodeyesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
old_textyesstring (at most 4096 characters)Exact tight-span text (node.edits option text).
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

list_element, op: insert: Insert one view element before or after an anchor.

FieldRequiredTypeMeaning
kindyes"list_element"Always this value.
opyes"insert"Always this value.
anchoryesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
positionyesbefore, afterInsert before or after the anchor.
old_textyesstring (at most 4096 characters)The anchor's exact current text, from its node.edits option.
elementyesstring (at most 16384 characters)Source of one view element, no indentation on its first line.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

declaration, op: create: Create a state or action in a page or component.

FieldRequiredTypeMeaning
kindyes"declaration"Always this value.
opyes"create"Always this value.
anchoryesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
positionyesbefore, after, firstbefore or after the anchor, or first in the owner.
old_textyesstring (at most 4096 characters)The anchor's tight text, or the owner's header line for position first.
declarationyesstring (at most 20000 characters)Source of the new state or action declaration (at most 20,000 characters).
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

declaration, op: update: Replace a state or action declaration, keeping kind and name.

FieldRequiredTypeMeaning
kindyes"declaration"Always this value.
opyes"update"Always this value.
nodeyesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
old_textyesstring (at most 20000 characters)The declaration's exact current text.
declarationyesstring (at most 20000 characters)The replacement source of the whole declaration.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

declaration, op: remove: Remove an unreferenced state or action.

FieldRequiredTypeMeaning
kindyes"declaration"Always this value.
opyes"remove"Always this value.
nodeyesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
old_textyesstring (at most 20000 characters)The declaration's exact current text.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

set_reference: Point an on_* handler at another action of the same owner.

FieldRequiredTypeMeaning
kindyes"set_reference"Always this value.
nodeyesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
propertyyesstring (at most 256 characters)Name of the handler property, such as on_press.
old_valueyesstring (at most 256 characters)The current action identifier.
targetyesstring (at most 1024 characters) or objectA node id of the base snapshot, or {handle} naming a node an earlier operation of the same batch created.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

import, op: add: Add one use line to a file.

FieldRequiredTypeMeaning
kindyes"import"Always this value.
opyes"add"Always this value.
pathyesstring (at most 1024 characters)Project-relative file path: forward slashes, no leading slash, no empty, . or .. segment, no backslash or control character.
import_kindyescomponent, modelWhat the use line imports: component or model.
symbolyesstring (at most 256 characters)Name of the component or model to import.
fromyesstring (at most 1024 characters)Relative path of the module that exports symbol.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

import, op: remove: Remove one use line whose symbol the file no longer references.

FieldRequiredTypeMeaning
kindyes"import"Always this value.
opyes"remove"Always this value.
pathyesstring (at most 1024 characters)Project-relative file path: forward slashes, no leading slash, no empty, . or .. segment, no backslash or control character.
symbolyesstring (at most 256 characters)Name of the imported component or model to remove.
old_textyesstring (at most 1024 characters)The exact use line.
handlenostringNames this operation's created node for later operations in the same batch (intra-batch handle).
expected_node_versionnostringOptional precondition: the node's version from node.get or node.edits.
optionnoobject (optionRef)Optional: the option_id and fingerprint of the matching node.edits option. A fingerprint that no longer matches is precondition_failed (option_stale).

replace_region: Fallback: replace the smallest whole-line region around a syntax error, offered by node.edits only on a syntax snapshot. The only operation of its batch (invalid_arguments, region_alone, otherwise); never a whole file.

FieldRequiredTypeMeaning
kindyes"replace_region"Always this value.
pathyesstring (at most 1024 characters)Project-relative file path: forward slashes, no leading slash, no empty, . or .. segment, no backslash or control character.
start_lineyesinteger (1..)1-based first line of the region.
end_lineyesinteger (1..)1-based last line of the region (inclusive); at most 200 lines in all.
old_textyesstring (at most 16384 characters)The region's exact text (node.edits option region.old_text): lines start_line..=end_line without the last newline.
new_textyesstring (at most 16384 characters)Replaces exactly the region's bytes; at most 200 lines and 16384 bytes (empty removes the lines' text).
optionyesobject (optionRef)Required: the region option (option_id r<N> and fingerprint) node.edits offered on this snapshot.

A proposal whose old_value is not the current value:

Request: change.propose with a wrong old_value
{"protocol": "axiom-agent-semantic/v1", "operation": "change.propose", "workspace": "<workspace>",
 "base_snapshot": "<snapshot>", "request_id": "rename-add-0",
 "params": {"operations": [{"kind": "set_property", "node": "element:Home/view/0/1", "property": "label",
   "old_value": "Create", "new_value": "Add task"}]}}
Response (excerpt)
{
  "error": {
    "code": "precondition_failed",
    "reason": "old_value_mismatch",
    "message": "label is \"Add\", expected \"Create\"",
    "operation_index": 0,
    "target": {
      "node": "element:Home/view/0/1",
      "property": "label"
    },
    "diagnostics": [],
    "retryable": "after_refresh",
    "next_actions": [
      {
        "operation": "node.get",
        "reason": "Re-read the node and rebuild the operation"
      }
    ]
  },
  …
}

With the current value:

Request: change.propose
{"protocol": "axiom-agent-semantic/v1", "operation": "change.propose", "workspace": "<workspace>",
 "base_snapshot": "<snapshot>", "request_id": "rename-add-1",
 "params": {"operations": [{"kind": "set_property", "node": "element:Home/view/0/1", "property": "label",
   "old_value": "Add", "new_value": "Add task"}]}}
Response (excerpt)
{
  "request_id": "rename-add-1",
  "result": {
    "candidate": {
      "id": "cand-…",
      "state": "open",
      "version": 1,
      …
    },
    "checks": [
      {
        "check": "compile",
        "status": "passed",
        …
      }
    ],
    "files": [
      {
        "after_sha256": "6fa9d35dbcf8…",
        "before_sha256": "c7ac07a1c507…",
        "change": "modified",
        "path": "main.acore"
      }
    ],
    "id_map": [],
    "operations": [
      {
        "id_map": [],
        "index": 0,
        "kind": "set_property"
      }
    ],
    "replayed": false,
    …
  },
  …
}

The same request_id with a different input:

Request: change.propose reusing a request_id
{"protocol": "axiom-agent-semantic/v1", "operation": "change.propose", "workspace": "<workspace>",
 "base_snapshot": "<snapshot>", "request_id": "rename-add-1",
 "params": {"operations": [{"kind": "set_property", "node": "element:Home/view/0/1", "property": "label",
   "old_value": "Add", "new_value": "Add a task"}]}}
Response (excerpt)
{
  "error": {
    "code": "conflict",
    "reason": "request_id_reused",
    "message": "request_id rename-add-1 was used for a different request (…); use a new request_id",
    "target": {
      "request_id": "rename-add-1"
    },
    "diagnostics": [],
    "retryable": "none",
    "next_actions": []
  },
  …
}

change.inspect

What a candidate changes: a semantic diff (each changed node and property, with expected: false for a change no operation asked for), a source diff or full content, affected nodes, risks and checks.

Params (schemas/operations/change.inspect.request.json)

FieldRequiredTypeMeaning
candidateyesstring (at most 256 characters)Opaque id of a private candidate (change.propose).
includenoarray of semantic_diff, source_diff, content, affected, checksWhich parts to return: semantic_diff, source_diff, content (full file content), affected, checks.

Result (schemas/operations/change.inspect.result.json)

FieldRequiredTypeMeaning
candidateyesobject (candidate)The candidate: id, version, state, snapshots, request_id and input fingerprint.
filesyesarray of object (fileChange), 1 to any itemsFiles the candidate changes, with SHA-256 before and after.
semantic_diffnoarray of objectEach changed node: added, removed, modified or relocated, with property values before and after, and whether an operation asked for it (expected).
source_diffnoarray of objectPer file, the changed lines as hunks. Bounded in size.
affectednoarray of object (nodeSummary)Summaries of the nodes the change affects.
risksnoarray of objectThings to review, each with a kind, a detail and optionally a node.
checksnoarray of object (checkResult)Result of each check on the candidate's current version.

candidate fields:

FieldRequiredTypeMeaning
idyesstring (at most 256 characters)Opaque id of a private candidate (change.propose).
versionyesinteger (1..)Increases with every successful change.propose on the candidate.
stateyesopen, applied, discarded, expiredThe candidate's state: open, applied, discarded or expired.
base_snapshotyesstring (at most 256 characters)Opaque id of one immutable captured snapshot. Never the reserved word latest.
snapshotyesstring (at most 256 characters)Snapshot id of base plus overlay; readable by the owning caller.
request_idyesstring (at most 128 characters)The request_id of the change.propose that produced this version.
input_fingerprintyesstringLowercase hex SHA-256 over a documented canonical input (node version, option fingerprint, input fingerprint).
expires_atnostringRFC 3339 with an explicit offset, uppercase T and Z.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired.

Request: change.inspect
{"protocol": "axiom-agent-semantic/v1", "operation": "change.inspect", "workspace": "<workspace>",
 "params": {"candidate": "<candidate>", "include": ["semantic_diff", "source_diff"]}}
Response (excerpt)
{
  "snapshot": {
    "id": "snap-2d2c561be58b…",
    "overlay": "cand-…",
    …
  },
  "result": {
    "semantic_diff": [
      {
        "change": "modified",
        "expected": true,
        "node": "element:Home/view/0/1",
        "properties": [
          {
            "after": "Add task",
            "before": "Add",
            "name": "label"
          }
        ]
      }
    ],
    "source_diff": [
      {
        "hunks": [
          {
            "lines": [
              "   view {",
              "     View {",
              "       Input(value: draft, placeholder: \"Add a task\")",
              "+      Button(label: \"Add task\", on_press: submit)",
              "-      Button(label: \"Add\", on_press: submit)",
              " ",
              "       if tasks.pending { Text(\"Loading...\") }",
              "       else if tasks.error { Text(\"Could not load tasks\") }"
            ],
            "old_start": 17,
            …
          }
        ],
        "path": "main.acore"
      }
    ],
    …
  },
  …
}

check.run

Runs checks on a candidate, or on a snapshot plus unsaved file contents (files, each with the SHA-256 of the file it replaces). The checks are compile and, on a broken base, repair. A failed check is a result with ok: false, never an error.

Params (schemas/operations/check.run.request.json)

FieldRequiredTypeMeaning
candidatenostring (at most 256 characters)Opaque id of a private candidate (change.propose).
filesnoarray of object (file), 0 to 64 itemsOverlay files; only with the envelope snapshot. [] checks the snapshot as is.
checksyesarray of string (at most 64 characters), 1 to any itemsChecks to run: compile or repair.

Result (schemas/operations/check.run.result.json)

FieldRequiredTypeMeaning
okyesbooleanTrue when every requested check passed.
candidatenostring (at most 256 characters)Opaque id of a private candidate (change.propose).
checksyesarray of object (checkResult), 1 to any itemsOne result per check: passed, failed, not_run or unavailable, with diagnostics.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, stale_snapshot, snapshot_expired.

Request: check.run
{"protocol": "axiom-agent-semantic/v1", "operation": "check.run", "workspace": "<workspace>",
 "params": {"candidate": "<candidate>", "checks": ["compile"]}}
Response (excerpt)
{
  "result": {
    "candidate": "cand-…",
    "checks": [
      {
        "check": "compile",
        "diagnostics": [
          {
            "column": 26,
            "line": 3,
            "message": "development contract `tasks` uses an unsigned local artifact; a production release requires Axiom Cloud signing",
            "path": "main.acore",
            "severity": "warning"
          }
        ],
        "status": "passed",
        …
      }
    ],
    "ok": true
  },
  …
}

To compile the files on disk now, name a snapshot and pass no files:

Request: check.run on the current files
{"protocol": "axiom-agent-semantic/v1", "operation": "check.run", "workspace": "<workspace>",
 "snapshot": "latest", "params": {"files": [], "checks": ["compile"]}}

change.apply

Writes a candidate to the project and returns a receipt. It first rechecks the candidate version, the required checks and that every file it writes still has the base content. See Apply, receipts and recovery.

Params (schemas/operations/change.apply.request.json)

FieldRequiredTypeMeaning
candidateyesstring (at most 256 characters)Opaque id of a private candidate (change.propose).
expected_candidate_versionyesinteger (1..)The candidate version you reviewed. Another version is precondition_failed (candidate_version_mismatch).
preconditionsnoarray of object, 1 to any itemsExplicit content preconditions (sha256 null: the file must not exist). Must include every written file when given.
require_checksnoarray of string (at most 64 characters)Checks that must have passed on this exact candidate version.

Result (schemas/operations/change.apply.result.json)

FieldRequiredTypeMeaning
replayedyesbooleanTrue when this is the recorded receipt of an earlier identical request.
receiptyesobjectThe receipt: what was written (see Apply, receipts and recovery).
base_changesnoarray of object (inputChange), 0 to 50 itemsInputs of the candidate's base snapshot that the candidate does not write and that differed on disk when it was applied (allowed by the content rule; a deleted or renamed one is refused instead). The published head is then not exactly the base plus the candidate. Absent when none, and on replays (replayed: true).

receipt fields:

FieldRequiredTypeMeaning
receipt_idyesstring (at most 128 characters)Id of this receipt.
request_idyesstring (at most 128 characters)Caller-chosen idempotency key, scoped to workspace and caller. Bound to the request's input fingerprint.
input_fingerprintyesstringLowercase hex SHA-256 over a documented canonical input (node version, option fingerprint, input fingerprint).
outcomeyesapplied, not_applied, unknownapplied (files written), not_applied (nothing written) or unknown (send the same request again with the same request_id).
candidateyesstring (at most 256 characters)Opaque id of a private candidate (change.propose).
candidate_versionyesinteger (1..)The candidate version that was applied.
base_snapshotyesstring (at most 256 characters)Opaque id of one immutable captured snapshot. Never the reserved word latest.
result_snapshotnostring (at most 256 characters)Captured after publication; present when applied.
filesyesarray of object (fileChange), 1 to any itemsEach written file with its SHA-256 before and after.
id_mapyesarray of object (idMap)Every node id the edit changed (completeness guarantee: an unlisted node keeps its id). [] when none.
journalyesobjectThe apply journal entry: its id and state (committed, rolled_back or pending_reconcile).
recorded_atyesstringRFC 3339 with an explicit offset, uppercase T and Z.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, precondition_failed, conflict, compile_failed.

Request: change.apply
{"protocol": "axiom-agent-semantic/v1", "operation": "change.apply", "workspace": "<workspace>",
 "request_id": "apply-rename-add-1",
 "params": {"candidate": "<candidate>", "expected_candidate_version": 1, "require_checks": ["compile"]}}
Response (excerpt)
{
  "request_id": "apply-rename-add-1",
  "result": {
    "receipt": {
      "base_snapshot": "snap-8d409ade6cc9…",
      "candidate": "cand-…",
      "candidate_version": 1,
      "files": [
        {
          "after_sha256": "6fa9d35dbcf8…",
          "before_sha256": "c7ac07a1c507…",
          "change": "modified",
          "path": "main.acore"
        }
      ],
      "id_map": [],
      "input_fingerprint": "…",
      "journal": {
        "id": "jrnl-…",
        "state": "committed"
      },
      "outcome": "applied",
      "receipt_id": "rcpt-…",
      "recorded_at": "…",
      "request_id": "apply-rename-add-1",
      "result_snapshot": "snap-2d2c561be58b…"
    },
    "replayed": false
  },
  …
}

Sending the same request again returns the recorded receipt and writes nothing:

Request: change.apply again
{"protocol": "axiom-agent-semantic/v1", "operation": "change.apply", "workspace": "<workspace>",
 "request_id": "apply-rename-add-1",
 "params": {"candidate": "<candidate>", "expected_candidate_version": 1, "require_checks": ["compile"]}}
Response (excerpt)
{
  "request_id": "apply-rename-add-1",
  "result": {
    "receipt": {
      "outcome": "applied",
      "receipt_id": "rcpt-…",
      "recorded_at": "…",
      …
    },
    "replayed": true
  },
  …
}

change.discard

Closes an open candidate and releases it. It never undoes an applied change; to undo, propose a compensating change.

Params (schemas/operations/change.discard.request.json)

FieldRequiredTypeMeaning
candidateyesstring (at most 256 characters)Opaque id of a private candidate (change.propose).
expected_candidate_versionnointeger (1..)Optional: the candidate version you expect. Another version is precondition_failed.

Result (schemas/operations/change.discard.result.json)

FieldRequiredTypeMeaning
candidateyesobject (candidate)The candidate, now discarded.
releasedyesbooleanOverlay resources were freed.

candidate fields:

FieldRequiredTypeMeaning
idyesstring (at most 256 characters)Opaque id of a private candidate (change.propose).
versionyesinteger (1..)Increases with every successful change.propose on the candidate.
stateyesopen, applied, discarded, expiredThe candidate's state: open, applied, discarded or expired.
base_snapshotyesstring (at most 256 characters)Opaque id of one immutable captured snapshot. Never the reserved word latest.
snapshotyesstring (at most 256 characters)Snapshot id of base plus overlay; readable by the owning caller.
request_idyesstring (at most 128 characters)The request_id of the change.propose that produced this version.
input_fingerprintyesstringLowercase hex SHA-256 over a documented canonical input (node version, option fingerprint, input fingerprint).
expires_atnostringRFC 3339 with an explicit offset, uppercase T and Z.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, precondition_failed.

Request: change.propose of a change to drop
{"protocol": "axiom-agent-semantic/v1", "operation": "change.propose", "workspace": "<workspace>",
 "base_snapshot": "<snapshot>", "request_id": "placeholder-1",
 "params": {"operations": [{"kind": "set_property", "node": "element:Home/view/0/0", "property": "placeholder",
   "old_value": "Add a task", "new_value": "New task"}]}}
Request: change.discard
{"protocol": "axiom-agent-semantic/v1", "operation": "change.discard", "workspace": "<workspace>",
 "params": {"candidate": "<candidate>", "expected_candidate_version": 1}}
Response (excerpt)
{
  "result": {
    "candidate": {
      "base_snapshot": "snap-2d2c561be58b…",
      "id": "cand-…",
      "input_fingerprint": "…",
      "request_id": "placeholder-1",
      "snapshot": "snap-9243a149fdcd…",
      "state": "discarded",
      "version": 1
    },
    "released": true
  },
  …
}

changes.since

What changed between an older snapshot (since) and the request's snapshot: changed files with digests, and where the nodes you hold (scope.nodes) are now. history is known, unknown or expired. Node mappings here are inferred (relation: inferred) from ids, paths and text.

Params (schemas/operations/changes.since.request.json)

FieldRequiredTypeMeaning
sinceyesstring (at most 256 characters)Opaque id of one immutable captured snapshot. Never the reserved word latest.
scopenoobjectLimit the answer to these node ids and paths.
cursornostring (at most 1024 characters)Opaque continuation token bound to one snapshot and one request shape. Valid until the snapshot expires.

Result (schemas/operations/changes.since.result.json)

FieldRequiredTypeMeaning
sinceyesstring (at most 256 characters)Opaque id of one immutable captured snapshot. Never the reserved word latest.
historyyesknown, unknown, expiredknown: deltas below are complete for scope. unknown: since is not related to this snapshot by captured history. expired: since was evicted; deltas are empty.
filesyesarray of object (fileChange)Files changed between the two snapshots, with digests before and after.
nodesyesarray of object (relocation)Where each node id you hold went, with the relation and basis (always inferred in this build).
relevantyesbooleanTrue when anything in scope changed (with scope.candidate: anything the candidate read or wrote).

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot.

Request: changes.since
{"protocol": "axiom-agent-semantic/v1", "operation": "changes.since", "workspace": "<workspace>",
 "snapshot": "latest",
 "params": {"since": "<first-snapshot>", "scope": {"nodes": ["element:Home/view/0/1"]}}}
Response (excerpt)
{
  "snapshot": {
    "id": "snap-2d2c561be58b…",
    …
  },
  "result": {
    "files": [
      {
        "after_sha256": "6fa9d35dbcf8…",
        "before_sha256": "c7ac07a1c507…",
        "change": "modified",
        "path": "main.acore"
      }
    ],
    "history": "known",
    "nodes": [
      {
        "basis": "path",
        "new_id": "element:Home/view/0/1",
        "old_id": "element:Home/view/0/1",
        "relation": "inferred",
        "status": "ok"
      }
    ],
    "relevant": true,
    "since": "snap-8d409ade6cc9…"
  },
  …
}

node.relocate

Maps up to 200 node ids from an older snapshot (from_snapshot) to the request's snapshot, one entry per id in request order. Each entry has a status, the new_id and the basis of the match (exact, text, path or missing); this build's matches are always relation: inferred.

Params (schemas/operations/node.relocate.request.json)

FieldRequiredTypeMeaning
from_snapshotyesstring (at most 256 characters)Opaque id of one immutable captured snapshot. Never the reserved word latest.
nodesyesarray of string (at most 1024 characters), 1 to 200 itemsNode ids from from_snapshot to map (1 to 200).

Result (schemas/operations/node.relocate.result.json)

FieldRequiredTypeMeaning
relocationsyesarray of object (relocation), 1 to 200 itemsOne entry per requested id, in request order: the new id or none, with relation and basis.

Error codes: invalid_arguments, not_found, internal, resource_limit, permission_denied, unsupported_operation, snapshot_expired, stale_snapshot, compile_failed.

Request: node.relocate
{"protocol": "axiom-agent-semantic/v1", "operation": "node.relocate", "workspace": "<workspace>",
 "snapshot": "latest",
 "params": {"from_snapshot": "<first-snapshot>", "nodes": ["element:Home/view/0/1", "state:Home.draft"]}}
Response (excerpt)
{
  "result": {
    "relocations": [
      {
        "basis": "path",
        "new_id": "element:Home/view/0/1",
        "old_id": "element:Home/view/0/1",
        "relation": "inferred",
        "status": "ok"
      },
      {
        "basis": "exact",
        "new_id": "state:Home.draft",
        "old_id": "state:Home.draft",
        "relation": "inferred",
        "status": "ok"
      }
    ]
  },
  …
}

Errors

An error response has error instead of result. Decide what to do from code, reason, retryable and next_actions; message is for people and may change.

The one-shot command and serve answer a request that is not valid JSON, is not a JSON object, or has no protocol field in the service's legacy format: error.code is invalid_request (not a v1 code), and there is no operation, retryable or next_actions. serve keeps reading the next line. For a request without a protocol field, the message is protocol is missing; it must be "studio/v1".

Over MCP, acore-semantic mcp answers a message that is not valid JSON with the JSON-RPC parse error -32700.

Ignore the studio/v1 named in that message: send axiom-agent-semantic/v1.

FieldRequiredTypeMeaning
codeyesunsupported_operation, invalid_arguments, ambiguous_owner, read_only_origin, stale_snapshot, precondition_failed, compile_failed, conflict, insufficient_context, snapshot_expired, permission_denied, resource_limit, not_found, internalOne of the closed list of error codes (see Error codes and what to do).
reasonnostringOpen refinement of code (the protocol reference lists the values in use), for example old_value_mismatch, request_id_reused, external_write.
messageyesstring (at most 4000 characters)A sentence for people. Do not parse it; use code and reason.
operation_indexnointeger (0..)Index in params.operations of the operation that failed (batched edits).
targetnoobject (target)What the error is about.
diagnosticsyesarray of object, 0 to 200 items (diagnostics)Compiler diagnostics, for example the errors of a candidate that did not compile.
retryableyesnone, same_request, after_refreshnone: the same request will fail again. same_request: retry unchanged (transient). after_refresh: re-read (new snapshot, node versions, options) and rebuild the request.
next_actionsyesarray of object (nextAction), 0 to 10 itemsSuggested next requests, each with the operation, why, and params when the service can fill them.
detailsnoobjectCode-specific structured data (current value, expansion refs, conflicting paths, receipt).

retryable is authoritative for each error:

retryableMeaningWhat to do
noneThe same request fails again.Change the arguments, scope, limits or approach. Do not loop.
same_requestTransient, or an apply that must be resolved.Send the identical request again, with the same request_id.
after_refreshYour view is out of date.Read again (new snapshot, node versions, options, values), rebuild the request and send it with a new request_id.

Error codes and what to do

CodeMeaningDefault retryableWhat a client should do
stale_snapshotThe base snapshot is not the current one, and a file the edit touches changed (reason base_not_head).after_refreshCall changes.since with your old snapshot and the ids you hold, map them, read the values again and propose on the current snapshot with a new request_id.
precondition_failedAn explicit precondition does not hold. Reasons: old_value_mismatch, old_text_mismatch, node_version_mismatch, option_stale, external_write, candidate_version_mismatch, candidate_closed, candidate_applied, incomplete_graph, check_required.after_refresh (candidate_applied: none)Read again with node.get or node.edits and rebuild the operation. On external_write at apply, someone edited the file: discard the candidate and start from latest.
insufficient_contextThe required context exceeds your limits. details.required_bytes and details.expand say what it needs.noneNarrow include or focus, then pass selected refs from details.expand. Raise max_bytes only up to the manifest maximum.
compile_failedThe base or the candidate does not compile; diagnostics has the compiler errors. Reasons include not_validated and repair_regression.noneRead diagnostics and operation_index, fix the operation and propose again. If the base is broken, start from project.overview diagnostics.
unsupported_operationThe protocol, operation, edit kind or option is not served. Reasons include protocol_unsupported, unknown_operation, not_implemented, edit_not_offered, still_referenced and group_unresolvable.noneDo not retry. Check capabilities and node.edits for a supported route. For still_referenced, remove the references first.
invalid_argumentsMalformed or unusable arguments (for example reason schema, no_op, incompatible_target, multiple_roots).noneFix the request against the schema.
ambiguous_ownerNo single authored owner (for example reason shadowed_name, duplicate_property). details.owners lists the choices when known.noneTarget one owner from details.owners explicitly, or ask the user. Never choose by text position.
read_only_originThe value is generated, inherited or owned by a dependency.noneEdit the owner that produces the value.
conflictrequest_id_reused, recovery_required (an interrupted apply left files that match neither the base nor the candidate) or concurrent_candidate.none (concurrent_candidate: after_refresh)Use a new request_id; for recovery_required stop and show the user the paths; for concurrent_candidate read again and propose again.
snapshot_expiredThe snapshot or candidate was evicted, or was stored by another compiler build.after_refreshRead again on latest; propose again if a candidate was lost.
permission_deniedOutside the attached root, or refused by policy (path_escape, root_not_allowed, not_owner, policy).noneDo not work around it.
resource_limitA service bound was hit; reason names it (see Limits).none; same_request for queue_full and for a change.apply that hit timeoutMake the request smaller or page it. For an apply timeout, follow After an apply timeout.
not_foundUnknown node, candidate, snapshot or workspace (for example reason snapshot_unknown, candidate_expired).noneFind the node again; never guess an id.
internalAn unexpected failure.same_request, onceRetry once unchanged, then report it.

Which operations can return each code (generated from each result schema's x-errors):

CodeOperations that can return it
unsupported_operationevery operation
invalid_argumentsevery operation
ambiguous_ownerchange.propose, edit.plan
read_only_originchange.propose, edit.plan
stale_snapshotproject.overview, node.find, node.get, node.edits, graph.query, context.build, impact.analyze, changes.since, node.relocate, change.propose, check.run, edit.plan
precondition_failedchange.propose, change.apply, change.discard, edit.plan
compile_failedworkspace.open, node.find, node.get, node.edits, graph.query, context.build, impact.analyze, node.relocate, change.propose, change.apply, edit.plan
conflictchange.propose, change.apply
insufficient_contextcontext.build
snapshot_expiredproject.overview, node.find, node.get, node.edits, graph.query, context.build, impact.analyze, changes.since, node.relocate, change.propose, change.inspect, check.run, change.apply, edit.plan
permission_deniedworkspace.open, project.overview, node.find, node.get, node.edits, graph.query, context.build, impact.analyze, changes.since, node.relocate, change.propose, change.inspect, check.run, change.apply, change.discard, edit.plan
resource_limitevery operation
not_foundworkspace.open, project.overview, node.find, node.get, node.edits, graph.query, context.build, impact.analyze, changes.since, node.relocate, change.propose, change.inspect, check.run, change.apply, change.discard, edit.plan
internalevery operation

Three more error examples, run after the apply above. An edit on the snapshot from before the apply, touching the file the apply changed:

Request: change.propose on an old snapshot
{"protocol": "axiom-agent-semantic/v1", "operation": "change.propose", "workspace": "<workspace>",
 "base_snapshot": "<first-snapshot>", "request_id": "rename-add-2",
 "params": {"operations": [{"kind": "set_property", "node": "element:Home/view/0/1", "property": "label",
   "old_value": "Add", "new_value": "Add item"}]}}
Response (excerpt)
{
  "error": {
    "code": "stale_snapshot",
    "reason": "base_not_head",
    "message": "base_snapshot snap-8d409ade6cc9… is not the current snapshot of the workspace (snap-2d2c561be58b…) and the files this request changes differ there",
    "target": {
      "snapshot": "snap-8d409ade6cc9…"
    },
    "diagnostics": [],
    "retryable": "after_refresh",
    "next_actions": [
      {
        "operation": "node.get",
        "reason": "Re-read the nodes on the current snapshot (snapshot.id of this response) and rebuild the request"
      }
    ]
  },
  …
}

An id that does not exist:

Request: node.get of an unknown id
{"protocol": "axiom-agent-semantic/v1", "operation": "node.get", "workspace": "<workspace>",
 "snapshot": "latest", "params": {"nodes": ["element:Home/view/9"]}}
Response (excerpt)
{
  "error": {
    "code": "not_found",
    "message": "element:Home/view/9 is not a node of snap-2d2c561be58b…",
    "target": {
      "node": "element:Home/view/9"
    },
    "diagnostics": [],
    "retryable": "none",
    "next_actions": [
      {
        "operation": "node.find",
        "reason": "Re-find the node on this snapshot"
      }
    ]
  },
  …
}

A protocol version the service does not speak:

Request: an unsupported protocol
{"protocol": "axiom-agent-semantic/v2", "operation": "capabilities", "params": {}}
Response (excerpt)
{
  "error": {
    "code": "unsupported_operation",
    "reason": "protocol_unsupported",
    "message": "protocol axiom-agent-semantic/v2 is not supported; this service speaks axiom-agent-semantic/v1…",
    "diagnostics": [],
    "retryable": "none",
    "next_actions": [
      {
        "operation": "capabilities",
        "reason": "Read the supported protocol and operations",
        "params": {}
      }
    ]
  },
  …
}

Limits

Request limits bound one response; omitted limits take the default, and values above the maximum are lowered (the response's truncation.limits shows what was applied). Service bounds are fixed. Generated from the manifest:

Request limitDefaultMaximum
max_bytes655364194304
max_depth216
max_items50200
max_nodes1001000
Service boundValue
request_max_bytes4194304
timeout_ms30000
group_compile_budget_ms20000
brackets_max8192
brackets_total_max16384
check_content_max_bytes2097152
check_files_max64
import_depth_max16
json_depth_max64
nesting_max256
operations_max50
snapshot_bytes_max67108864
source_file_bytes_max2097152
source_files_max64
sources_bytes_max4194304

Each bound has one error: resource_limit with a specific reason:

ReasonBound
request_too_largeRequest over request_max_bytes
json_depth_limitRequest nested deeper than json_depth_max
too_many_operationsMore than operations_max operations in change.propose or edit.plan
content_too_largecheck.run file contents over check_content_max_bytes
nesting_limit, bracket_limit, brackets_total_limitBracket nesting or count in a source file, an overlay or a candidate
file_too_large, sources_too_large, too_many_modules, import_depth_limitProject source size, file count or import depth
snapshot_too_largeCaptured inputs over snapshot_bytes_max
budget_exhaustedA batch's intermediate compiles past group_compile_budget_ms
timeoutA request running past timeout_ms
queue_fullThe service is busy; retry the same request

A limit violation is never compile_failed or a failed check: the check could not run. Bounds on single arguments stated in the schemas (for example a string new_value over 4096 characters) are invalid_arguments with reason schema.

Apply, receipts and recovery

change.apply publishes a candidate to the local filesystem:

  1. It checks the candidate version, that the required checks passed on that version, and that every file it writes still has the base content (a file the candidate creates must not exist). If not, it writes nothing: precondition_failed (external_write) for a file edited since, conflict (concurrent_candidate) for a file another candidate on the same base wrote.
  2. It writes a journal and backups, then replaces the files one at a time (write, sync, rename). Each file is replaced atomically; the set of files is not atomic for other readers.
  3. It returns a receipt: receipt_id, request_id, input_fingerprint, outcome, the candidate and its version, base_snapshot, result_snapshot (when applied), each file's SHA-256 before and after, the id_map, the journal entry and the time.

outcome is applied, not_applied or unknown. unknown means the service could not tell whether writing finished, for example after an interrupted rename; its journal stays pending_reconcile. The next change.apply with the same request_id reconciles first: it returns the recorded receipt if the files match the candidate, applies the candidate if they match the base, and otherwise answers conflict (recovery_required) without writing.

Inputs of the base that the candidate does not write are checked too: one deleted or renamed since is precondition_failed (external_write), and one edited since is accepted and listed in the result's base_changes.

After an apply timeout

The time limit answers the client; it cannot undo or finish what the apply was doing. A change.apply past timeout_ms is answered with:

  • code: resource_limit, reason: timeout, retryable: same_request;
  • target: the candidate and the request_id;
  • next_actions: change.apply with the same params;
  • details: outcome, timeout_ms, and receipt when one exists.

details.outcome is about this attempt:

  • not_applied: this attempt stopped before it started writing and can no longer start. An earlier attempt with the same request_id may still have applied the change.
  • unknown: this attempt had started writing, or reconciling an earlier attempt, and the service cannot tell how far it got. The files may already hold the candidate. details.receipt is the unknown receipt when the journal was written.

In both cases, send the same change.apply again with the same request_id. The server process exits after a timed-out request, so start it again first (for an MCP client, reconnect the server if its tools are gone). The answer is the recorded receipt with replayed: true, or the interrupted apply is reconciled from its journal and the candidate is applied once. A resend with the same request_id is never request_id_reused and never applies twice. Do not propose again, use a new request_id, or edit the files by hand to retry an apply: after the change was applied, a new request_id for the same candidate is precondition_failed (candidate_applied).

Guarantees and their limits

Publication is proven against process kills at every step: after a kill the apply ends applied, rolled back, or reported as needing attention, with no half-written file. It is not proven against power loss or operating system crashes, and there is no remote publication. The full list of guarantees is in the Support matrix.

Compatibility

The manifest's protocol.status is frozen, and protocol.frozen_operations lists the operations frozen in v1: capabilities, workspace.open, project.overview, node.find, node.get, node.edits, graph.query, context.build, impact.analyze, changes.since and node.relocate. Read that list from capabilities rather than from this page. Error code is a closed list; reason is an open string that can gain values. A client sends an optional field only when capabilities lists the operation as implemented. A planned operation or edit kind answers unsupported_operation (not_implemented).