# Specification This page summarizes the `agent-graph.*.v1` protocols implemented by `@c4a/agent-graph@0.3.1`. The JSON Schemas shipped in the package's `schemas/` directory are normative for file shape; this page lists fields and behavioural rules. For the reasoning behind them, read [Core Model](); for step-by-step use, read [Authoring Graphs](). | Schema identity | Object | | --- | --- | | `agent-graph.provider.v1` | Provider manifest | | `agent-graph.graph.v1` | Graph | | `agent-graph.action.v1` | Action | | `agent-graph.resource.file.v1`, `.graph-action.v1`, `.host-action.v1` | Resource descriptors | | `agent-graph.resource-location.file.v1`, `.graph-action.v1`, `.host-action.v1` | Resolved Resource locations | | `agent-graph.resource-read-receipts.v1` | Current-conversation read receipts | | `agent-graph.host-action-result.v1` | Host materialization result | | `agent-graph.code-catalog.v1` | Code Catalog | | `agent-graph.evaluation.v1`, `agent-graph.route.v1` | Evaluation and Route output | | `agent-graph.run.v1` | Run file | | `agent-graph.test.v1` | Graph test | | `agent-graph.bundle.v1` | Built bundle manifest | | `agent-graph.error.v1` | CLI error envelope | Unknown fields are rejected in every v1 object, so a misspelled safety field cannot be silently ignored. ## Provider and Skill binding ```yaml schema: agent-graph.provider.v1 id: company/release version: 0.1.0 graphs: [graphs/release.yaml] catalogs: codes: codes.yaml compatibility: agentGraph: ^0.3.0 node: ">=20" ``` | Field | Rule | | --- | --- | | `id` | Identifies the Provider; runtime identities are qualified by Provider, Graph and node ID | | `version` | Semantic version of this Provider, independent of the `@c4a/agent-graph` package version | | `graphs` | Provider-root-relative paths; Graphs are never discovered by scanning | | `catalogs.codes` | Optional Code Catalog | | `compatibility` | Supported toolchain (`agentGraph`) and Node.js ranges | All references stay inside the Provider root: no absolute paths and no escape through `..` or a symbolic link. Several Providers stay isolated — no merging and no cross-Provider Subgraphs. A source manifest may have any filename; a built bundle uses `provider.yaml` plus a generated `manifest.json`. A bound Skill declares `metadata.agent-graph` (a `path:` locator relative to that `SKILL.md`, or a host-resolved `provider:` locator), `agent-graph.graph` and `agent-graph.entry`. The three are validated together, and an Agent must never infer Graph or Entry from prose. ## Graph and nodes A Graph has `id`, `entrypoints` (public entry name → node), `nodes` and `edges`. Topology is static: target names, dates, phase IDs and queue items are Facts, not generated nodes. Every Graph needs at least one Terminal; Terminals have no outgoing edges, and reaching Terminals with conflicting Outcomes is `terminal-outcome-ambiguous` with status `error`. | Kind | Required field | Meaning | | --- | --- | --- | | `action` | `action` | A Provider-relative Action can be selected | | `gate` | `gate` | User or session authority must resolve a policy boundary | | `subgraph` | `graph`, `entry` | Enter another Graph in the same Provider | | `terminal` | `terminalOutcome` | End the frame with an explicit Outcome | | Common field | Rule | | --- | --- | | `description` | Short human label, never a condition | | `reasonCode` | Required on Action and Gate nodes; shape `route.` | | `priority` | Ranks Routes within one availability class; never a semantic chooser | | `join` | `all` (default) requires all incoming edges; `any` requires one | | `requiresFacts` | All checks must pass before the node is legal | | `satisfiedBy` | Facts that prove an Action or Gate complete without replaying it | | `resources.required`, `resources.recommended` | Resources selected with an Action or Gate | Subgraph and Terminal nodes cannot carry Action or Gate resources or satisfaction rules. ## Fact checks ```yaml satisfiedBy: - path: artifact.digest exists: true - path: verification.state equals: passed ``` `path` is a dotted lookup in which numeric segments index arrays (`items.0.digest`). Each check has exactly one of `exists` or `equals`, with a scalar JSON value. There is no JavaScript, templating, shell or condition language. | Situation | Result | | --- | --- | | `satisfiedBy` matches | `completed`, even with no Run record | | Recorded `completed`, `satisfiedBy` does not match | `unverified` | | Explicit `unverified` edge | Can route to recovery | | A claim made in conversation | Creates no Fact | ## Gates | Field | Rule | | --- | --- | | `gate.id`, `gate.prompt` | Gate identity and a short question | | `gate.authority` | Authority that may resolve it | | `gate.delegatable` | Only when true can a session authority resolve it | | `inspectionAction` | Optional `effect: read` Action that prepares evidence; exposed as `gate.inspectionAction`, safe while waiting | | `resolutionAction` | Optional `write` or `external` Action that records or applies the decision after confirmation; exposed as `gate.resolutionAction` | | `delegated.inspection` | `skip` hides the inspection on the delegated Route; requires an authored inspection Action | | `delegated.resolutionAction` | Replaces the resolution Action on the delegated Route only; `write` or `external` | | `delegated.resources` | Replaces the Gate's resources on the delegated Route only | Without the authority the Route is `waiting-user` with an empty `commandPlan`; with a delegatable authority it is actionable with `resolution: session-authority`. Authorities live in the current input or Run, never in the Provider, and never satisfy Facts. A host must not run a resolution Action while the Route still requires the user. ## Edges Each edge has `from`, `to`, optional `kind` and optional `outcomes` (default `[completed]`). | Kind | Semantics | | --- | --- | | `flow` | General control transition | | `consumes` | The target consumes an artifact produced by the source | | `requires` | The source is a legal prerequisite of the target | | `gatedBy` | A Gate resolves the target's policy boundary; must start at a Gate | | `repeat` | A matching Outcome resets an Action or Gate to pending | All non-repeat kinds share the same reachability rule; the kind records causal intent only. Edges carry no runtime values. Non-repeat edges must be acyclic (`graph-flow-cycle` otherwise), `repeat` must target an Action or Gate, and Run history keeps earlier iterations. Fan-out and fan-in are reachability, not concurrency. A Subgraph target is resolved statically in the same Provider; recursion into an ancestor is rejected. ## Actions ```yaml schema: agent-graph.action.v1 id: inspect-package runner: command effect: read command: npm pack --dry-run cwd: workspace ``` | Runner | Fields | Route result | | --- | --- | --- | | `command` | `command` | Exact shell command | | `script` | `entry`, `runtime`, optional `args` | Runtime and absolute installed entry path | | `agent` | `skill` | The Skill as a required file resource | | `host` | `handler` | Host-defined handler identity | | Field | Rule | | --- | --- | | `effect` | Required: `read`, `write` or `external` | | `cwd` | `workspace` (default) or `provider` | | `inputSchema`, `outputSchema` | Bundled; installed locations exposed on the Route | | `files` | Extra runtime files to package | Runner fields are mutually exclusive. A Skill in its own directory carries that directory into the bundle; a Provider-root `SKILL.md` carries only itself. Agent Graph resolves Actions and never executes them implicitly. ## Resources | Protocol | Key fields | Behaviour | | --- | --- | --- | | Static file | Markdown frontmatter `id`, `kind`, `media-type`; or a `resource.file.v1` descriptor with `id`, `kind`, `mediaType`, `path` | Kinds `procedure`, `diagnostic`, `template`, `schema`, `skill`; located by absolute path, media type and content digest | | Graph action | `id`, `kind: context-view`, `mediaType`, `materializer` | Materializer must be a `read` command or script Action; runs only through `resource materialize` with the selecting Route revision | | Host action | `id`, `kind`, `mediaType`, `materializer`, `input` | Materializer must be a `read` host Action with `handler`, `inputSchema` and `outputSchema`, each schema with a versioned protocol identity; input validated before any Route is returned | Materializers receive `AGENT_GRAPH_PROVIDER_ROOT`, `AGENT_GRAPH_WORKSPACE`, `AGENT_GRAPH_REVISION` and `AGENT_GRAPH_INPUT`, a minimal inherited environment, and default limits of 30 s, 10 MiB stdout and 1 MiB stderr. For host-action Resources, Agent Graph computes `input_digest` from `{handler, input.schema, input.value}`; the host returns `agent-graph.host-action-result.v1` with the same handler and digest, adapter identity and exactly one of `inline` or `resource` (`ref` plus `digest`), checked by `validateHostActionResult`. Read receipts (`agent-graph.resource-read-receipts.v1`) are scoped to one Provider. A static receipt matches ID and digest; a dynamic one matches ID and selecting Route revision. Every Route resource gets `readState: current` or `read-required`. Receipts never affect evaluation and are never persisted in Runs. ## Code Catalog ```yaml schema: agent-graph.code-catalog.v1 codes: - code: route.release.inspect kind: route-reason summary: The release artifact still needs inspection. document: resources/release-checklist.md ``` `kind` is `route-reason` or `diagnostic` (which may add `severity`, including `info`). `summary` is a hint, never a condition; `document` is an optional static Resource. Without a Catalog, `reasonCode` is only shape-checked; with one, every Action and Gate `reasonCode` must resolve to a `route-reason` entry. ## Outcomes, Evaluation and Route Outcomes are `completed`, `partial`, `failed`, `unverified`, `skipped`, `pending`, `blocked` and `waiting-user`. They are not aliases; `partial`, `unverified` and `skipped` never become `completed`. | Evaluation field | Content | | --- | --- | | `provider`, `graph`, `entry` | Identities | | `revision` | Digest of the Graph's same-Provider dependency closure, Facts, normalized Outcomes and authorities | | `statusCode` | `actionable`, `waiting-user`, `blocked`, `complete` or `error` | | `outcome` | Terminal Outcome, when complete | | `primaryRoute`, `alternativeRoutes` | One primary and up to three alternatives, each with `routeId`, `node`, `reasonCode`, optional `hint`, `availability` | | `diagnostics` | Compact diagnostics | Evaluation is read-only and deterministic; outcome timestamps and files used only by unrelated Graphs do not change the revision. A Route (`agent-graph.route.v1`) carries `revision` and `routeId`, Graph, node and `callPath`, `statusCode`, `reasonCode`, `hint`, `availability`, optional Gate resolution and Gate Actions, the Action with its effect, `commandPlan` or handler, resolved working directory, required and recommended resource locations — each keeping its complete file, Graph-action or Host-action location envelope — with `readState`, and `afterAction: {evaluate: true, recordNode}`. A Route ID is accepted only while still available, and a revision mismatch is rejected before any command plan is returned. ## Run, tests and bundle A Run (`agent-graph.run.v1`) is optional host-owned memory: Provider, Graph, entry, optional workspace, Facts, the latest Outcome per state key, session authorities, append-only numbered events and timestamps. A checkpoint is a validated copy without authorities; resume copies it to an explicit path, clears authorities and appends an event. No default state directory exists. A graph test (`agent-graph.test.v1`) declares `state` (`facts`, `outcomes`, `authorities`) and `expect` assertions, and never executes Actions or calls a model; see [Testing and Publishing](). `build` validates everything reachable, copies reachable files, writes a normalized `provider.yaml` and a `manifest.json` with catalogs, file digests, the Graph dependency index and an overall digest, excludes tests, refuses to overwrite sources and rejects any file containing the source absolute path. Loading a bundle rejects digest mismatches, missing or extra files, incomplete catalogs, identity mismatches and inconsistent dependency indexes. ## Compatibility Until `@c4a/agent-graph` reaches `1.0.0`, the v1 family is in public draft finalization: a `0.x` release may tighten a required field or invariant, but must document the break and update every shipped template, example and test. `0.2.0` made Action and Gate `reasonCode` mandatory and completed the Skill binding with explicit Graph and Entry fields; `0.3.0` replaced the numbered Resource and Resource Location protocols with separate file, Graph-action and Host-action protocols. After `1.0.0`, incompatible semantics need a new schema version and compatible additions need a defined extension point. Hosts branch on schema identities, status codes, reason codes and diagnostic codes — never on human text. Version-by-version changes are in [Migration](). --- ## Sources - [agent-graph/docs/en/specification.md L1–L3 · 9e8b98a]() - [agent-graph/docs/en/specification.md L402–L406 · 9e8b98a]() - [agent-graph/package.json L1–L4 · 9e8b98a]() - [agent-graph/docs/en/specification.md L5–L41 · 9e8b98a]() - [agent-graph/docs/en/specification.md L43–L82 · 9e8b98a]() - [agent-graph/docs/en/specification.md L84–L105 · 9e8b98a]() - [agent-graph/docs/en/specification.md L107–L135 · 9e8b98a]() - [agent-graph/docs/en/specification.md L137–L170 · 9e8b98a]() - [agent-graph/docs/en/specification.md L172–L202 · 9e8b98a]() - [agent-graph/docs/en/specification.md L204–L252 · 9e8b98a]() - [agent-graph/docs/en/specification.md L252–L276 · 9e8b98a]() - [agent-graph/docs/en/specification.md L278–L309 · 9e8b98a]() - [agent-graph/docs/en/specification.md L311–L328 · 9e8b98a]() - [agent-graph/docs/en/specification.md L330–L367 · 9e8b98a]() - [agent-graph/docs/en/specification.md L369–L400 · 9e8b98a]() - [agent-graph/docs/en/specification.md L402–L410 · 9e8b98a]()