Skip to content

The delegation-first operating model — local LLM + graph-os do the work; the harness orchestrates + resolves exceptions

The architecture-doc form of the canonical AGENTS.md discipline "Delegate to the KG + graph-os — the operator are the orchestrator + exception-resolver". Concepts: KG-2.296 (:ToolCall / RunTrace provenance) · AU-ORCH.scheduling.resource-priority-edict/1.99 (resource-priority edict) · AU-ECO.mcp.full-api-mcp-surface (full engine MCP/REST surface) · ORCH-1.95/96/97 (the execution seam) · ORCH-1.100/1.101 (the agent-utilities-expert) · AU-KG.retrieval.kg-4 (cross-layer troubleshooting) · AU-KG.research.these-properties-carry / AU-KG.research.evolutionstate-live-surface-per/2.291 (the Loop engine + evolution state) · AU-OS.config.autonomous-spec-develop-off (the spec review-veto gate) · AU-AHE.optimization.telemetry-optimization (the hardening loop).

The principle

The platform is built so that the local LLM + graph-os do the work, and Claude / the harness orchestrates and resolves exceptions. The standing default is delegate as much as possible; reserve direct action for what the autonomous system genuinely cannot do yet — the trajectory is to orchestrate off the harness over time.

This is not a style preference; it is the design center of the whole system. Every sub-system documented elsewhere — the execution seam, the expert agent, the troubleshoot provider, the engine surface, the resource-priority edict — exists to make delegation both capable (the local model can actually run the work against real tools) and safe (every run is fully visible, steerable, and non-starving).

The operator's job as the harness becomes two things:

  1. Orchestrate — decompose a goal, dispatch it to graph-os / the local LLM, and steer it (query live EvolutionState, the :ToolCall / RunTrace provenance, reprioritize, approve/veto).
  2. Resolve exceptions — when a delegated run fails, returns a wrong or ungrounded answer, or the system couldn't self-troubleshoot, that is the operator's job: read the RunTrace / :ToolCall to see exactly what the local LLM did, find why, fix the gap, and re-delegate.

The three delegation routes

Before doing anything the operator, route it to one of three delegation paths.

1. Understand code → the KG, never grep first

To learn how an area works, where a symbol is used, or what a change impacts, query the code KG first:

graph_code action=code_context  query="<area/symbol/question>"  target=how|usage|impact

(REST POST /graph/code, CONCEPT:AU-KG.retrieval.synthesized-cited-answer.) how returns a definition + what it calls + owning CONCEPT + docs + routes; usage returns callers (file:line) + near-clones + the cross-repo usage view (AU-KG.retrieval.every-usage-published-symbol); impact returns transitive callers (blast radius) + git change-coupling. Read only the few file:lines the operator must edit, not to understand — then close the loop with graph_feedback correction_type=reads_avoided (AU-AHE.evaluation.reads-avoided-feedback) so the retriever learns which answers replace a read. If an area is uningested, source_sync source=all mode=delta first, then fall back to grep. (See codebase-context.md.)

2. Do a task → graph_orchestrate on the local LLM

Hand a task an ingested skill / workflow / agent can already do to the local model:

act intent="<task>" tool=graph_orchestrate
graph_orchestrate task="<task>"                       # KG selects skill/workflow
graph_orchestrate agent=agent-utilities-expert task="<ecosystem task>"
graph_orchestrate agent=<ingested-skill> task="…"
graph_workflows action=execute workflow=<workflow> task="…"

The normal Codex path supplies only the intent. graph_orchestrate resolves a typed, ingested skill or workflow from the KG, runs it on local vLLM, and binds authenticated fleet MCP tools inside GraphOS; Codex never installs the skill body or loads the child tool schemas. An explicit agent remains available as a pin. The agent-utilities-expert is the fallback delegate when the KG has no typed skill/workflow hit — a native, KG-bound persona that grounds its answers in graph-os instead of hallucinating (see agent-utilities-expert.md). Either way the execution seam (orchestration-execution-seam.md) runs it on the local vLLM against real MCP tools and writes full provenance. Reach the rest of the ~58-server fleet via the engine_<domain> surface + the multiplexer meta-tools (find_tools / load_tools).

3. Evolve / manage the ecosystem → the loop engine + review-veto

Drive the Loop engine (graph_loops / LoopController, AU-KG.research.these-properties-carry) and the evolution flywheel + the AU-AHE.optimization.telemetry-optimization hardening loop — and review their proposals rather than hand-doing what the flywheel produces. The research→assimilation→distill→develop pipeline turns research/concepts into first-class, queryable :SpecProposal nodes (AU-KG.research.close-distill-develop-seam) that enter the promotion pipeline only after the AU-OS.config.autonomous-spec-develop-off spec-review checkpoint approves them — propose-and-hold (veto) is the default. Read live EvolutionState (graph_loops action=state, AU-KG.research.evolutionstate-live-surface-per) and the saturation gauge (AU-KG.research.saturation-gauge-aggregates-four) to know which direction is exhausted, and approve/veto rather than implement by hand.

flowchart TD
    H["Claude / harness<br/>(orchestrator + exception-resolver)"]
    H -->|understand code| KG["graph_code code_context<br/>(KG-2.134/135) → cited answer"]
    H -->|intent only| EX["graph_orchestrate skill gateway<br/>KG resolves skill / workflow"]
    EX -->|no typed hit| EXP["agent-utilities-expert fallback"]
    EX -->|workflow DAG| WF["governed WorkflowRunner<br/>local LLM per step"]
    H -->|evolve/manage| LOOP["graph_loops + evolution flywheel<br/>:SpecProposal → AU-OS.config.autonomous-spec-develop-off review-veto"]
    EX --> ENGINE["engine_&lt;domain&gt; surface (AU-ECO.mcp.full-api-mcp-surface)<br/>+ multiplexer meta-tools"]
    EX --> PROV[":ToolCall / RunTrace provenance (KG-2.296)<br/>+ run_id handle (AU-ORCH.execution.rich-result-wrapper)"]
    PROV -->|query: what did it do?| H
    PROV -->|on failure| TS["troubleshoot provider (AU-KG.retrieval.kg-4)<br/>read RunTrace → find why"]
    TS --> FIX["fix the gap: missing skill / unbound tool /<br/>prompt / ingestion"]
    FIX -->|re-delegate + harden (AU-AHE.optimization.telemetry-optimization)| EX
    EDICT["resource-priority edict (AU-ORCH.scheduling.resource-priority-edict/99)<br/>orchestration outranks ingestion"] -.guards.- EX
    EDICT -.guards.- H

The full engine surface available to delegates (AU-ECO.mcp.full-api-mcp-surface)

agent-utilities is the native API/MCP layer for the Rust epistemic-graph engine. The curated high-level graph_* / ontology_* / object_* tools cover the synthesized, agent-facing operations; AU-ECO.mcp.full-api-mcp-surface adds complete 1:1 coverage of the engine's low-level capability surface so no engine method is reachable only from a Python import. A delegate (or the harness) reaches it through the multiplexer like any other tool.

  • One action-routed MCP tool per engine domain — engine_<domain> — each a thin generic dispatcher that resolves the engine client and calls getattr(client.<domain>, action)(**params_json), with its REST twin /engine/<domain> registered in the same call (surface-parity gate stays green). Implementation: agent_utilities/mcp/tools/engine_tools.py → register_engine_tools.
  • Drift-free by introspection (AU-KG.compute.engine-surface-manifest) — the action set per domain is discovered by introspecting the epistemic_graph client sub-client classes (the 19 sub-clients = nodes, edges, graph, analytics, lifecycle, reasoning, ledger, channels, tenants, resharding, consensus, finance, datascience, query, txn, timeseries, rdf, streaming, blob — ~222 methods). A new engine method shows up automatically once the client wraps it; no hand-maintained list to rot.
  • Granular 1:1 surface, never listed — one engine_<domain>_<method> operation per method is still generated (from ENGINE_DOMAINS, via gen_graphos_manifest) and registered on graph-os's private backing server, reachable as act(action="engine_<domain>.<method>") or through ask's natural-language routing — without placing the full set in tools/list or the resident model context.

This is why the delegation-first model can push heavy compute to the engine (vector similarity, ANN, graph algorithms, ML math, finance) instead of writing an O(N) include Python: the full engine is one MCP call away. Python orchestrates; the engine computes.

What makes delegation safe and non-starving

Provenance — :ToolCall / RunTrace (KG-2.296)

Every delegated run writes its provenance to the epistemic-graph: a run-level RunTrace with an opaque canonical id and a first-class :ToolCall node per tool call the local LLM made, linked (:RunTrace)-[:USED_TOOL]->(:ToolCall), capturing tool_name, privacy-guarded content digests/counts, status, and sequence. The MCP execute_agent / execute_workflow surfaces return a run_id handle (AU-ORCH.execution.rich-result-wrapper) so a delegation is trackable. This is the keystone: full visibility + steerability is guaranteed by design — query a run over graph-os and see which tools the local LLM called and correlate opaque payload digests without disclosing durable raw payloads. Mechanics in orchestration-execution-seam.md.

The resource-priority edict (AU-ORCH.scheduling.resource-priority-edict/1.99)

Interactive / orchestration work outranks background ingestion, so the operator's orchestration is never starved by the system's own ingestion. The engine keeps a reserved interactive read lane so orchestration reads aren't blocked under a write-storm, and admission tags delegated runs ORCHESTRATION/INTERACTIVE so they are never stuck behind ingestion enrichment. See resource-priority-edict.md. Without this, "delegate everything" will let a re-ingest sweep starve the very control plane the operator orchestrate through; with it, delegation scales.

The exception-resolution loop

When a delegated run fails, is ungrounded, or the system couldn't self-troubleshoot — that is the harness's job. The loop:

  1. Read the provenance. Call graph_jobs action=status with the public run handle, then use its returned trace_id for graph_query MATCH (t:RunTrace {id: $trace_id})-[:USED_TOOL]->(tc:ToolCall) RETURN … ORDER BY tc.sequence, or drive the troubleshoot provider (graph_explain action=explain target="troubleshoot:run" node_id=<run_id>, troubleshooting.md) to trace across every layer (app → container → system → host → cross-cutting).
  2. Find why. The first failing :ToolCall (wrong tool, bad args, unbound tool, a 502/exit 137 traced down the stack) is usually the root.
  3. Fix the gap. A missing or weak skill, an unbound tool, a prompt, missing data/ingestion — fix the one thing that made the local LLM fail.
  4. Re-delegate, and harden so the system self-handles that case next time: add the skill, fix the tool binding, harden the prompt, capture the gotcha via graph_feedback — the AU-AHE.optimization.telemetry-optimization hardening loop. Every exception the operator resolve should make the autonomous system one step more autonomous.

The goal is to orchestrate completely off the harness: the local LLM + graph-os handle the work, the operator handle the shrinking set of exceptions, and each exception the operator resolve shrinks that set further.

Delegation probe ownership and migration

scripts/delegation_probe.py is the intended versioned agent-utilities ownership point for the direct, in-process delegation gate. It calls the orchestration core and imports agent-utilities internals, so its stage exit status is an agent-utilities release criterion. The workspace-root scripts/delegation_probe.py is currently divergent; it is not yet a compatibility shim. D-CDX-11 and D-CDX-19 remain open until this lane lands and the root file is replaced, under the workspace-scripts lease, by a forwarding shim to the tracked agent-utilities script.

Its grounding stage is a gate only for --grounding=required: a production latency budget overrun or retrieval_quality_gate_failed stops the probe at stage 4 (exit 4). Required mode performs exactly one preflight compile by default and cannot select zero samples. best_effort and none skip synthetic compiles by default and proceed directly to the real delegation. An explicit positive --grounding-samples count enables benchmarking under any policy, and stage detail labels preflight, benchmark, and skipped functional operation distinctly. The bounded measurement still uses wait_for(to_thread(...)); its known non-cancelling worker/shutdown-tail limitation is D-CDX-22 and is intentionally not changed by this efficiency behavior.

The toolset stage is a catalog-only exact binding check: it checks the configured endpoint and the durable server-to-tool declaration, but does not open an MCP transport. The delegated execution owns the one refresh-capable MCPToolset session, including live schema/list-changed behavior, cancellation, and teardown. A missing or empty catalog fails the probe before delegation rather than treating an unverified tool as bound.