Run agents with agent-runtime
@tangle-network/agent-runtime is the execution substrate for exact, measurable agent runs. It turns an AgentProfile into a real execution, coordinates one or many agents under conserved budgets, records what actually happened, and keeps candidate promotion separate from live activation.
Combined with @tangle-network/agent-provider-tangle, it runs any supported coding agent — Claude Code, Codex, OpenCode, Kimi Code, and more — in a Tangle sandbox with full accounting.
Install
pnpm add @tangle-network/agent-runtime @tangle-network/agent-interface @tangle-network/agent-provider-tangle @tangle-network/sandboxQuickstart: one agent in a Tangle sandbox
import { Sandbox } from "@tangle-network/sandbox";
import { createTangleProvider } from "@tangle-network/agent-provider-tangle";
import { providerAsSandboxClient, runAgentRounds } from "@tangle-network/agent-runtime/kernel";
import type { AgentProfile } from "@tangle-network/agent-interface";
// 1. Connect to Tangle Sandbox
const sandbox = new Sandbox({
apiKey: process.env.TANGLE_API_KEY!,
baseUrl: "https://sandbox.tangle.tools",
});
// 2. Wrap the sandbox as an environment provider
const provider = createTangleProvider({ client: sandbox });
// 3. Adapt the provider into the runtime's sandbox client
const client = providerAsSandboxClient(provider);
// 4. Define the agent you want to run
const profile = {
name: "my-claude-agent",
harness: "claude-code", // or "codex", "opencode", "kimi-code", "pi"
model: { provider: "anthropic", default: "anthropic/claude-sonnet-4-6" },
} satisfies AgentProfile;
// 5. Run it
const result = await runAgentRounds({
task: "Review the last 5 commits and summarize the changes.",
driver: {
plan: async (task, history) => (history.length === 0 ? [task] : []),
decide: () => "done" as const,
},
agentRun: { profile, taskToPrompt: (t) => t },
output: { parse: (events) => events },
ctx: { sandboxClient: client },
});
console.log(`decision: ${result.decision} — ${result.iterations.length} iteration(s)`);What the runtime gives you
| Capability | What it means |
|---|---|
| Exact execution | One declared harness, provider, model, tool surface, and profile is the execution that actually runs. No silent substitution. |
| Agent control | Turns, tool loops, retries, supervision trees, graph traversals, steering, cancellation, and durable resume. |
| Truthful accounting | Outputs, failures, tokens, dollars, timing, traces, and provider identity are observed facts. Unknown never becomes zero or success. |
| Independent completion checks | A worker is delivered because a check passed, not because the worker said it finished. |
| Budget conservation | scope.spawn reserves from a shared pool atomically and fails closed when the pool can’t cover it. |
Multi-agent supervision
Run a supervisor that spawns children on a conserved budget pool:
import {
createSupervisor,
definePersona,
fanout,
runPersonified,
type Agent,
type Scope,
} from "@tangle-network/agent-runtime/kernel";
// A driver that spawns two children, drains them, picks the best
const driver: Agent<string, unknown> = {
name: "two-arm-driver",
act: async (task: string, scope: Scope<unknown>) => {
// Each spawn RESERVES its whole ceiling from the shared pool atomically
const [arm1, arm2] = await Promise.all([
scope.spawn({ task: `${task} (arm A)`, ceiling: { usd: 0.50 } }),
scope.spawn({ task: `${task} (arm B)`, ceiling: { usd: 0.50 } }),
]);
// Drain both, then select the best valid settlement
const results = await Promise.all([arm1.result, arm2.result]);
return results.find((r) => r.ok) ?? results[0];
},
};
const persona = definePersona({
agent: driver,
profile: { harness: "claude-code", model: { provider: "anthropic", default: "anthropic/claude-sonnet-4-6" } },
});
// Run under a supervisor with a budget ceiling
const outcome = await runPersonified({
persona,
task: "Review this PR from two angles: correctness and style.",
budget: { usd: 1.00 },
ctx: { sandboxClient: client },
});Agent graphs
Compose planner, worker, and reviewer agents into a graph whose every step runs in a sandbox:
import { promptHandle, runGraph } from "@tangle-network/agent-runtime/kernel";
const plan = promptHandle("Review the failing tests and propose a fix.");
const implement = promptHandle("Implement the fix you proposed.");
const review = promptHandle("Review the implementation. Approve or request changes.");
const graph = {
nodes: { plan, implement, review },
edges: [
{ from: "plan", to: "implement" },
{ from: "implement", to: "review" },
// review can loop back to implement if changes are requested
],
};
for await (const event of runGraph(graph, { sandboxClient: client })) {
if (event.type === "node_complete") {
console.log(`${event.node}: ${event.outcome.type}`);
}
}Supported harnesses
Every sandbox ships these pre-installed. Set profile.harness to the ID:
| Harness ID | Agent | Requires |
|---|---|---|
claude-code | Claude Code | Anthropic key or Claude subscription token |
codex | OpenAI Codex | OpenAI key or ChatGPT login |
opencode | OpenCode | Any OpenAI-compatible endpoint |
kimi-code | Kimi Code | Moonshot API key |
pi | Pi | Pi API key |
cli-base | Generic CLI agent | Any provider |
What belongs where
| Package | Owns |
|---|---|
agent-runtime | Execution, budgets, supervision, accounting |
agent-eval | Scoring, comparison, statistical tests, promotion gates |
sandbox | Isolated Linux environments |
agent-provider-tangle | Adapter from Sandbox to the provider contract |
The packages release independently. Compatibility is proven through packed-consumer tests.