Harness Descriptor
The harness descriptor is a supported 0.2.x API for describing an agent graph
as data.
It does not make an application declarative. The application still owns tool implementations, policies, provider setup, persistence, approvals, and context lifecycle.
Core Idea
Section titled “Core Idea”A descriptor defines:
- runtime defaults such as entry agent and max turns
- logical tool ids and registry targets
- agents, model settings, tools, and handoffs
- optional context defaults
- context paths that instruction templates may read
The application binds executable tools through a registry and then calls
buildAgentHarness(...).
Descriptor Shape
Section titled “Descriptor Shape”interface AgentHarnessDescriptor { descriptor_version?: string; metadata?: Record<string, unknown>; runtime: { entry_agent: string; max_turns?: number; }; context?: { fields?: Record<string, HarnessContextFieldDescriptor>; references?: Record<string, HarnessContextReferenceEntry>; }; instruction_parts?: Record<string, string>; tools?: Record<string, { target: string }>; agent_defaults?: { model?: string; modelSettings?: Record<string, unknown>; instructions?: string | HarnessInstructionPartDescriptor[]; }; agents: Record<string, HarnessAgentDescriptor>;}
interface HarnessInstructionPartDescriptor { text: string; where?: { context: string; };}Building
Section titled “Building”import { buildAgentHarness } from "@axiastudio/aioc";
const harness = buildAgentHarness(descriptor, { registryVersion: "customer-support-tools@1", tools: { "example://tool/lookup_order": lookupOrder, },});If you keep prompts in separate Markdown files, load and materialize the YAML first:
agents: router: instructions_file: ./prompts/router.md
game_master: instructions_files: - ./prompts/shared.md - ./prompts/game-master.md instructions: |- Inline instructions are appended after the listed files.import { buildAgentHarness, loadAgentHarnessDescriptorFromFile,} from "@axiastudio/aioc";
const descriptor = await loadAgentHarnessDescriptorFromFile( "./harness.yaml",);const harness = buildAgentHarness(descriptor, registry);instructions_file and instructions_files are resolved relative to the
descriptor file and replaced by instructions before the descriptor reaches
buildAgentHarness(...). Lists are joined in order with blank lines; inline
instructions after instructions_files are appended last.
For richer composition, use a top-level instruction_parts catalog and an
agent-level instructions_sequence:
instruction_parts: company_context: |- COMPANY CONTEXT: {{context.prompt.companyInstructionsText}} ---
context: references: "prompt.companyInstructionsText": type: string optional: true "prompt.includeCompanyContext": type: boolean
agents: qna: instructions_sequence: - ref: company_context where: context: prompt.includeCompanyContext - text: |- You must ALWAYS invoke find_chunks before answering. - file: ./prompts/qna-extra.mdEach instructions_sequence item must define exactly one of:
ref: reusable text from top-levelinstruction_partstext: agent-local inline instructionsfile: local prompt file resolved by the loader
The optional where.context path must be declared under context.references
with type: boolean. It is evaluated when agent instructions are resolved for a
run. Parts whose where value is not exactly true are skipped.
The returned harness contains:
entryAgentagentsrunOptionsmetadatadescriptorHashcreateContext(...)
Use it with run(...):
const result = await run(harness.entryAgent, "Check order ORD-1001", { ...harness.runOptions, context, policies,});Tool Registry
Section titled “Tool Registry”Descriptors never contain executable tool code.
They map logical ids to application-owned targets:
tools: lookup_order: target: example://tool/lookup_order
agents: order: tools: [lookup_order]The registry supplies the real tool implementation:
buildAgentHarness(descriptor, { tools: { "example://tool/lookup_order": lookupOrder, },});Context Fields
Section titled “Context Fields”context.fields describes values that createContext(...) can default.
context: fields: "turn.userMessage": type: string default: "{{input.message}}"Only fields with default are materialized by createContext(...).
Supported default placeholders:
{{input.message}}{{runtime.now_iso}}
Context References
Section titled “Context References”context.references describes values that instruction templates may read from
the run context.
context: references: "prompt.learningStyleLabel": type: stringInstructions can then use:
Learning style: {{context.prompt.learningStyleLabel}}Important rules:
- references are exact paths
- declaring
promptdoes not allowprompt.learningStyleLabel fieldsdoes not grant prompt accessreferencesdoes not create default values- placeholders are path references only, not JavaScript expressions
Hashing
Section titled “Hashing”hashAgentHarnessDescriptor(...) and harness.descriptorHash identify the
descriptor content passed to buildAgentHarness(...).
When using loadAgentHarnessDescriptorFromFile(...) or
loadAgentHarnessDescriptor(...) with a promptMap, prompt file content from
instructions_file, instructions_files, or instructions_sequence file
items is materialized into instructions before hashing, so prompt text changes
alter the descriptor hash.
The hash does not include executable runtime behavior such as:
- registry implementation
- provider setup
- policy logic
- persistence
- approval workflows
For audit records, include descriptor metadata together with registry, provider, policy, and package metadata.
Boundaries
Section titled “Boundaries”Keep these outside the descriptor:
- provider credentials
- tool implementation code
- policy definitions
- approval lifecycle logic
- database or persistence configuration
- arbitrary JavaScript expressions
- unresolved
instructions_file,instructions_files, orinstructions_sequenceentries passed directly tobuildAgentHarness(...)
The descriptor should make the agent graph inspectable, not replace the application runtime.