> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentium.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Run a graph and reuse its result

> Execute a provider-free three-node calculation with ExecutionGraphRuntime and verify completed output is retained without another dispatch.

Run two independent fixture reads and a dependent sum through a versioned host catalog. Invoke the completed task again and verify that all three callback results are retained. No provider, database or external service is called.

| You will use | Requirement |
| - | - |
| Packages | Matching `@agentium/core`, `@agentium/harness`, `zod` |
| Runtime | Node 22.18+ within v22 or 24.11+ within v24 |
| Result | `{ left: 2, right: 3, total: 5 }`; three total dispatches across both runs |
| Persistence | Process-local fixture; `capabilities.durable` is false |

## Get the project

[Download the complete TypeScript project](https://github.com/agentiumOS/agentium/releases/download/v4.9.0/execution-graph.zip). This archive targets **Agentium 4.9.0** and installs matching published core/harness packages. The project includes source, dependencies, a compiler configuration and run instructions; see [installation](/learn/installation) for runtime requirements.

For a manual project, install the matching core/harness packages plus `zod`, `typescript`, `tsx` and `@types/node`; set `"type": "module"` in `package.json`. Save as `execution-graph.ts`:

```typescript execution-graph.ts theme={null}
import { pathToFileURL } from "node:url";
import { InMemoryDurableTaskStore } from "@agentium/core";
import { ExecutionGraphRuntime, type GraphToolBinding } from "@agentium/harness";
import { z } from "zod";

export async function runCalculation() {
  let dispatches = 0;
  const valueInput = z.object({ value: z.number() }).strict();
  const sumInput = z.object({ left: z.number(), right: z.number() }).strict();
  const reference = z.object({
    $ref: z.object({ node: z.string().min(1), path: z.array(z.string()).length(0) }).strict(),
  }).strict();
  const value: GraphToolBinding = {
    id: "value", version: "1", kind: "tool",
    input: valueInput, output: z.number(), referenceOutputs: [""],
    recovery: "pure", // The host attests that no external mutation occurs.
    tool: {
      name: "value", description: "Read a fixture value", parameters: valueInput,
      execute: async (args) => { dispatches++; return JSON.stringify(valueInput.parse(args).value); },
    },
  };
  const sum: GraphToolBinding = {
    id: "sum", version: "1", kind: "tool",
    input: sumInput, output: z.number(), referenceInputs: ["left", "right"],
    validateTemplate: (template) => {
      z.object({ left: reference, right: reference }).strict().parse(template);
    },
    recovery: "pure",
    tool: {
      name: "sum", description: "Add two fixture values", parameters: sumInput,
      execute: async (args) => {
        dispatches++;
        const input = sumInput.parse(args);
        return JSON.stringify(input.left + input.right);
      },
    },
  };
  const graph = new ExecutionGraphRuntime({
    store: new InMemoryDurableTaskStore(), // Local fixture; cannot survive process loss.
    catalog: [value, sum],
    program: { id: "calculation", version: "1", plan: {
      schemaVersion: 1, revision: 1,
      nodes: [
        { id: "left", binding: "value", version: "1", args: { value: 2 } },
        { id: "right", binding: "value", version: "1", args: { value: 3 } },
        { id: "total", binding: "sum", version: "1", args: {
          left: { $ref: { node: "left", path: [] } },
          right: { $ref: { node: "right", path: [] } },
        } },
      ],
    } },
    limits: { maxConcurrentWork: 2, maxExpandedNodes: 3,
      maxWorkAttempts: 3, maxPlanRevisions: 1 },
    harness: { grants: { toolIds: ["value", "sum"], modelRoles: [] },
      budgets: { maxModelCalls: 0, maxToolCalls: 3, maxTokens: 0 } },
  });
  const identity = { tenantId: "demo", actorId: "reader", sessionId: "calculation",
    runId: "calculation-run", rootRunId: "calculation-run" };
  const key = { tenantId: identity.tenantId, taskId: "calculation-task" };
  await graph.create({ id: key.taskId, input: {}, identity, deadline: Date.now() + 60_000 });
  const first = await graph.run(key, "worker-1");
  const second = await graph.run(key, "worker-2");
  const output = z.object({ left: z.literal(2), right: z.literal(3), total: z.literal(5) }).parse(second.output);
  console.log("status:", first.task.state, "output:", JSON.stringify(output));
  console.log("dispatches after retained result:", dispatches);
  console.log("persistent store:", graph.capabilities.durable);
  return { first, second, dispatches, output, durable: graph.capabilities.durable };
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  await runCalculation();
}
```

## Run and inspect the outcome

```bash theme={null}
npx tsx execution-graph.ts
```

The command prints a completed task, the three expected output fields, **three dispatches after retained result**, and `persistent store: false`. The second worker retrieves the completed output without reserving new dispatch attempts. `inspect(key)` can read evidence without claiming or mutating the task.

References infer data dependencies. The catalog declares exact permitted input/output paths and validates future-value templates, then the runtime resolves and validates actual values before dispatch. Explicit root limits cap concurrency, unique node incarnations, work attempts and revisions. The fixture permits zero model calls and exactly three tool calls.

## Adapt the binding and store

| Change | Keep this property |
| - | - |
| Replace fixture reads | Validate concrete arguments/output and version callable behavior |
| Add a mutation | Use a versioned durable connector and retained receipt; a pure declaration is unsuitable |
| Survive process loss | Supply verified durable atomic CAS/fencing and set `requireDurable: true` |
| Use an Agent node | Restrict static configuration, bounded outputs and approved catalog tools |
| Ask a model for the graph | Keep host instructions/grants authoritative and bound proposals/corrections |

This fixture proves local completed-task reuse, not a process-crash or external-effect guarantee. Persistent adapters need their own failure-window tests. Cancellation does not undo accepted work, and fencing cannot physically stop a remote request. Follow the [recoverable graph guide](/harness/execution-graphs) before connecting a durable backend or effect destination.

The fixture owns no network clients or persistent data. Hosts own the lifecycle of a persistent store and shared providers; `ExecutionGraphRuntime` has no general store-close method. Next, compare [ordinary Workflow graphs](/workflows/graphs) or add [bounded planning](/harness/execution-graphs#add-bounded-model-planning).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.