Core features
Agent Lineage
A causal DAG (directed acyclic graph) that traces the full chain from human prompt to tool call result. Each node hashes its parent — tamper-evident by construction. Exportable as JSON or PDF for compliance documentation.
How it works
When a human sends a message to an agent, the agent makes tool calls to fulfil it. Each tool call may trigger sub-calls. Lineage captures this causal tree: who called what, in what order, with what parameters and result.
Each lineage node contains:
- Node ID (UUID)
- Parent node ID (null for the root human prompt)
- Tool name, agent ID, server name
- Input parameters, output, error status
- Timestamp, duration
- SHA-256 hash of
parent_hash + tool_name + agent_id + input
The hash chain means the graph cannot be retroactively altered — the same integrity model as a blockchain, applied to AI agent audit trails. This satisfies EU AI Act Art. 12 record-keeping requirements for tamper-evidence.
Enabling lineage
import { createMCPProxy, MemoryLineageStore } from "@businys/ops"
const proxy = createMCPProxy({
lineage: {
store: new MemoryLineageStore(),
// Optional: custom context extractor
// getContext: (req) => ({ sessionId: req.headers["x-session-id"] }),
},
})Passing lineage context
To link a tool call to a parent (e.g. the human message that triggered it), pass the parent node ID in the X-Lineage-Parent request header:
// When sending the human message, create a root lineage node
// The agent framework passes the root node ID to child tool calls
fetch("http://localhost:3101/mcp", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Lineage-Parent": rootNodeId, // from LINEAGE_HEADERS
},
body: JSON.stringify(toolCallPayload),
})Reading lineage chains
import { MemoryLineageStore, verifyLineage } from "@businys/ops"
const store = new MemoryLineageStore()
// Get the full chain for a call
const chain = await store.getChain(nodeId)
// chain.nodes — array of LineageNode in causal order
// chain.valid — boolean: hash chain verified
// Verify integrity
const valid = await verifyLineage(chain)
// Export as JSON for compliance documentation
const json = JSON.stringify(chain, null, 2)LineageNode shape
| Field | Type | Description |
|---|---|---|
id | string | UUID for this node |
parentId | string | null | Parent node ID, null for root |
toolName | string | MCP tool name |
agentId | string | Agent that made the call |
serverName | string | MCP server name |
input | Record<string, unknown> | Tool call arguments |
output | string | Tool call result |
isError | boolean | Whether the call returned an error |
durationMs | number | Call duration in milliseconds |
timestamp | number | Unix timestamp ms |
hash | string | SHA-256 of parent_hash + tool_name + agent_id + input |
Compliance use
Agent Lineage directly addresses EU AI Act Art. 13 (transparency — system output interpretable by deployers) and Art. 12 (record-keeping — tamper-evident logs). See comply.businys.dev/articles for the full article mapping.
To export a lineage chain as a compliance artifact:
const chain = await store.getChain(rootNodeId)
const artifact = {
exportedAt: new Date().toISOString(),
verified: await verifyLineage(chain),
nodeCount: chain.nodes.length,
chain: chain.nodes,
}
fs.writeFileSync("lineage-export.json", JSON.stringify(artifact, null, 2))