# How Child Agent Usage Statistics Are Attributed to Parent Sessions in Prime Agent

> Understand how Prime Agent attributes child agent usage to parent sessions. Learn about ChildUsageAttributionEntry merging token counts, costs, and cache metrics for clear auditing.

- Repository: [Prime Intellect/prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)
- Tags: internals
- Published: 2026-09-05

---

**Child agent usage statistics are attributed to parent sessions through a `ChildUsageAttributionEntry` record that merges token counts, cost, and cache metrics into the parent turn's usage summary while preserving individual child entries for audit purposes.**

Prime Agent's hierarchical agent architecture allows parent sessions to spawn child (sub-agent) runs for delegated tasks. When these child runs complete, their resource consumption—tokens, API costs, and cache operations—must roll up into the parent's usage totals. The `PrimeIntellect-ai/prime-agent` repository implements this through a formal attribution mechanism that balances aggregation with traceability.

## The Attribution Mechanism

The flow begins when a child run finishes and produces a `Usage` object from its final assistant message, defined in [`packages/ai/src/types.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/ai/src/types.ts). Rather than immediately mutating the parent session, Prime Agent creates a persisted attribution entry that enables both aggregation and debugging.

### ChildUsageAttributionEntry Structure

The core data structure is defined in [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/session-manager.ts) (lines 62-68):

| Field | Description |
|-------|-------------|
| `type` | Fixed value `"child_usage_attributed"` |
| `targetId` | ID of the parent assistant message that spawned the child |
| `childUsage` | Raw `Usage` object from the child run |
| `aggregateUsage` | Running total of all child usage for this parent turn |
| `origin` | Attribution trigger: `"spawn_task"`, `"agent_message"`, or `"direct_user"` |

### Merging Usage into Parent Sessions

The actual merge operation occurs through `addAssistantUsage(parentUsage, childUsage)` in [`packages/coding-agent/src/core/usage.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/usage.ts) (lines 34-43). This function:

- Adds `input` and `output` token counts
- Accumulates `cacheRead` and `cacheWrite` statistics
- Updates `totalTokens` and `cost.total`

The parent session's in-memory `Usage` object is updated immediately, while the `ChildUsageAttributionEntry` is appended to the session log for persistence and UI inspection.

## Code Implementation

### Creating and Persisting Attribution Entries

```typescript
import { addAssistantUsage, emptyUsage } from "./usage.js";
import type { Usage } from "@earendil-works/pi-ai";

// Child usage returned from sub-agent completion
const childUsage: Usage = {
  input: 1200,
  output: 400,
  cacheRead: 0,
  cacheWrite: 0,
  totalTokens: 1600,
  cost: { total: 0.02 },
};

// Initialize or retrieve parent message usage
const parentUsage: Usage = emptyUsage();

// Merge child metrics into parent totals
addAssistantUsage(parentUsage, childUsage);

// Create persisted audit record
const attribution: ChildUsageAttributionEntry = {
  type: "child_usage_attributed",
  id: crypto.randomUUID(),
  parentId: parentMessageId,
  timestamp: new Date().toISOString(),
  targetId: parentMessageId,  // Links to spawning message
  childUsage,                 // Original child metrics
  aggregateUsage: parentUsage, // Updated running total
  origin: "agent_message",     // How child was invoked
};

// Append to session log
sessionManager.appendEntry(attribution);

```

### Reading Aggregated Usage from Sessions

```typescript
import { Session } from "@prime-agent/coding-agent";

const session = await Session.load(sessionFile);
const parentMsg = session.getMessageById(parentMessageId);

// Usage includes all child contributions
const totalUsage = parentMsg.message.usage;

console.log(`Total tokens: ${totalUsage.totalTokens}`);
console.log(`Total cost: $${totalUsage.cost.total.toFixed(4)}`);

```

## UI Presentation in the Tree Selector

The interactive TUI component at [`packages/coding-agent/src/modes/interactive/components/tree-selector.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/interactive/components/tree-selector.ts) surfaces child usage attribution at three locations (approximately lines 308, 558, and 784). When rendering nodes, it checks for entries with `type === "child_usage_attributed"`:

```tsx
// Tree-selector.ts excerpt
if (entry.type === "child_usage_attributed") {
  const { childUsage, aggregateUsage } = entry;
  
  return (
    <NodeBadge>
      Child: {childUsage.totalTokens} tokens
      <Tooltip>
        Aggregate: {aggregateUsage.totalTokens} tokens
        Origin: {entry.origin}
      </Tooltip>
    </NodeBadge>
  );
}

```

This allows operators to see both the immediate child contribution and the cumulative impact of all children spawned from a parent turn.

## Test Coverage

Three test suites verify the attribution pipeline:

- **[`session-manager/file-operations.test.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/session-manager/file-operations.test.ts)** — Confirms `ChildUsageAttributionEntry` persistence with correct `childUsage` and `aggregateUsage` values
- **[`agent-session-recursion.test.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/agent-session-recursion.test.ts)** — Integration test validating that parent usage reflects child usage after recursive agent execution
- **[`context-tree.test.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/context-tree.test.ts)** — Ensures the UI's context-tree properly folds child entries into parent node displays

These tests cover the complete lifecycle: generation, persistence, in-memory aggregation, and UI rendering.

## Summary

- **Attribution entries** (`ChildUsageAttributionEntry`) link child usage to parent messages via `targetId` while preserving original metrics
- **Usage merging** through `addAssistantUsage()` aggregates tokens, cost, and cache statistics into parent totals
- **Dual persistence** maintains both running aggregates (for summaries) and individual entries (for debugging)
- **UI integration** in [`tree-selector.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/tree-selector.ts) exposes child breakdowns without cluttering the main session view

## Frequently Asked Questions

### How does Prime Agent distinguish between direct LLM calls and child agent usage?

Direct LLM calls update the parent message's `usage` field immediately. Child agent usage follows a two-step process: the child's `Usage` object is stored in a `ChildUsageAttributionEntry`, then merged via `addAssistantUsage()`. The `origin` field tracks whether the child was spawned via `spawn_task`, `agent_message`, or `direct_user` invocation.

### Can I inspect individual child usage after it's been aggregated?

Yes. The `ChildUsageAttributionEntry` preserved in the session log contains the original `childUsage` object unchanged. Load the session file and filter entries by `type: "child_usage_attributed"` to see per-child breakdowns regardless of aggregation state.

### What performance overhead does usage attribution add?

Minimal. `addAssistantUsage()` performs simple numeric addition on six fields. The attribution entry itself is a small JSON object appended to the session log. According to the source at `usage.ts:34-43`, no complex calculations or external I/O occur during the merge operation.

### Does aggregation handle nested children (grand-child agents)?

Yes. When a child spawns its own children, their usage rolls into the child first, then the child complete's `Usage` (now including its descendants) rolls into the grandparent. The `aggregateUsage` field at each level captures the full subtree, creating a complete hierarchical accounting.