Specification • Wiki • Why Circuitry? • Building Runtimes
Circuitry is a tiny source format for executable AI graphs.
It exists because AI orchestration should not be trapped inside framework glue, hidden prompts, vendor runtimes, or one-off scripts. The orchestration layer deserves its own durable artifact: a file you can read, install, inspect, version, compose, and run.
Circuitry makes that artifact small.
circuitry: "0.4"
title: Minimal assistant
inputs:
user_turn:
type: text
required: true
entry: assistant
resources:
turn:
type: input
from: user_turn
system:
type: text
value: You are concise.
assistant:
type: agent
inputs: [system, turn]
tools: []
instructions: Answer the user.
output:
response: str
outputs:
response:
from: assistant.responseA Circuitry file separates the graph boundary from the graph body.
inputsare graph invocation inputs/arguments.resourcesdefine the internal graph.resources.*.inputsare resource dependencies.resources.*.outputis the resource output schema/contract.- top-level
outputsare named graph-level exported outputs.
Prompts are inputs/text resources. Tools are runtime functions explicitly declared by a graph resource. Graphs are executable topology. Resources are the graph.
A model can consume the graph. A human can review it. A runtime can execute it. Another graph can import it. An agent can write a new one.
AI systems increasingly need to author, install, and run new structures instead of only calling fixed tools. Circuitry gives those structures a shared file format.
That means a graph can define:
- an assistant loop
- a research pipeline
- a code repair strategy
- a context recovery pass
- a compaction routine
- a reusable subgraph another agent can request
The same file can be inspected before it runs, carried between runtimes, checked into git, packaged, reviewed, or generated by an agent.
npm install @darkhorseprojects/circuitrycircuitry check graph.circuitry.yaml
circuitry resolve graph.circuitry.yaml
circuitry inspect graph.circuitry.yamlresolve returns a resolved resource graph in the same Circuitry 0.4 shape. There is no public compiled node/edge format.
circuitry: "0.4"
title: string
description: string
imports: []
inputs: {}
entry: resource_id
entries: {}
resources: {}
outputs: {}Top-level inputs and outputs are the graph's public interface.
inputs:
user_turn:
type: text
required: true
resources:
turn:
type: input
from: user_turn
assistant:
type: agent
inputs: [turn]
output:
answer: str
outputs:
final:
from: assistant.answerresources.turn.from binds the external input user_turn into the internal resource graph.
assistant.output declares the expected schema of the assistant resource's materialized value.
outputs.final.from exports assistant.answer as the graph result named final.
In from: assistant.answer, assistant is the resource id and answer selects a field/path inside that materialized resource value. Without a dot, the whole materialized resource value is referenced.
Internal graph wiring uses resource.inputs, not top-level outputs. output is schema-only and does not define graph exports.
Import renaming is assignment-style.
imports:
- path: ./shared.circuitry.yaml
resources:
system: base_systemsystem = imported.base_systemThis imports base_system from the imported graph and binds it locally as system. The current graph should reference system.
entry is the default resource to run. entries are named entry aliases, so one graph can expose multiple useful executable entrypoints.
entry: assistant
entries:
chat: assistant
recover: recovered_contextRuntimes may run a graph from any explicit entry, alias, or resource they support.
Tools are an explicit graph-declared tool surface.
resources:
assistant:
type: agent
tools: [read, write, bash]A runtime must not expose undeclared tools to that resource. Circuitry only declares tool names; the runtime defines what each tool means and how it executes. Zinc implements tools such as read, write, edit, bash, and run_graph.
Unknown fields are preserved. Circuitry tooling validates and interprets core fields only. Runtimes may interpret additional fields they understand. Portable meaning is guaranteed only for fields defined by the Circuitry spec.
Unknown resource types are allowed so runtimes can extend behavior. Circuitry stays small by defining stable graph primitives instead of encoding every workflow feature.
A graph can include a resource that represents running another graph.
resources:
turn:
type: input
from: user_turn
session_log:
type: input
from: session_log
recovered_context:
type: run
graph: ./context-recovery.circuitry.yaml
entry: recovery
inputs:
user_turn: turn
session_log: session_log
assistant:
type: agent
inputs: [turn, recovered_context]
tools: [read, write, bash, run_graph]type: run is declarative topology. Its output describes the result of the graph run. A runtime tool like run_graph is dynamic capability.