# PostToolUse vs PreToolUse Hooks in AgentMemory: Capture Pipeline Differences

> Understand PostToolUse vs PreToolUse hooks in agentmemory capture pipelines. Learn how PreToolUse prepares context and PostToolUse records tool outputs for indexing and replay.

- Repository: [Rohit Ghumare/agentmemory](https://github.com/rohitg00/agentmemory)
- Tags: internals
- Published: 2026-05-10

---

**PreToolUse hooks enrich the model's input context before tool execution (optional and opt-in), while PostToolUse hooks persist tool outputs as durable observations for indexing and replay (always active).**

AgentMemory is an open-source observability framework for Claude Code that captures filesystem and tool interactions through a dual-stage hook pipeline. Understanding the difference between **PostToolUse** and **PreToolUse** hooks is critical for customizing how context is injected into model turns versus how execution history is recorded. This analysis examines the implementation in `rohitg00/agentmemory` to clarify their distinct roles in the capture architecture.

## Execution Timing and Core Purpose

The capture pipeline processes every tool invocation—such as `Edit`, `Write`, `Read`, `Glob`, or `Grep`—through two sequential hooks that operate at different phases of the tool lifecycle.

### PreToolUse: Context Enrichment Before Execution

The **PreToolUse** hook executes **before** a tool call is sent to Claude Code. Its primary function is to optionally inject relevant context—such as file lists or search terms—into the upcoming model turn.

In [`src/hooks/pre-tool-use.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/hooks/pre-tool-use.ts), the hook reads the tool payload from `stdin` and checks the `AGENTMEMORY_INJECT_CONTEXT` environment variable (lines 9–23). If disabled, the hook exits immediately (lines 34–37) without modifying the workflow. When enabled, it extracts file paths and patterns (lines 56–68), then sends a JSON payload to the `/agentmemory/enrich` REST endpoint. Any `context` string returned by the server is written to `stdout` (lines 90–94), which Claude Code reads and prepends to the next model turn.

### PostToolUse: Observation Persistence After Execution

The **PostToolUse** hook executes **after** a tool call returns its result. Its purpose is to create a permanent record of the interaction for later retrieval, compression, and replay.

Located in [`src/hooks/post-tool-use.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/hooks/post-tool-use.ts), this hook always runs regardless of environment settings. It extracts image data using `extractImageData` (lines 60–88), truncates large outputs to 8,000 characters using the `truncate` function (lines 93–101), and POSTs an observation to `/agentmemory/observe` with `hookType: "post_tool_use"` (lines 33–53). The payload includes the session ID, tool name, input parameters, and processed output.

## Configuration and Activation Behavior

The two hooks differ fundamentally in their activation models and operational requirements.

**PreToolUse** is **opt-in** and disabled by default. It imposes token costs since injected context consumes model context window. Activate it by setting:

```bash
AGENTMEMORY_INJECT_CONTEXT=true

```

**PostToolUse** is **always active** and cannot be disabled via environment variables. The hook is registered unconditionally in the capture pipeline because AgentMemory requires these observations for core functionality like session replay and audit logging.

## Payload Structures and Data Flow

Each hook communicates with different REST endpoints and produces distinct data structures.

The PreToolUse hook sends enrichment requests to `/agentmemory/enrich`:

```typescript
const res = await fetch(`${REST_URL}/agentmemory/enrich`, {
  method: "POST",
  headers: authHeaders(),
  body: JSON.stringify({
    sessionId: "s-123",
    files: ["src/index.ts"],
    terms: [],
    toolName: "Read"
  })
});

```

The response context is streamed to `stdout` for Claude Code consumption, but **no observation is created** in the memory store.

The PostToolUse hook sends observation records to `/agentmemory/observe`:

```typescript
await fetch(`${REST_URL}/agentmemory/observe`, {
  method: "POST",
  headers: authHeaders(),
  body: JSON.stringify({
    hookType: "post_tool_use",
    sessionId: "s-123",
    project: process.cwd(),
    cwd: process.cwd(),
    timestamp: new Date().toISOString(),
    data: {
      tool_name: "Write",
      tool_input: { "file_path": "src/util.ts", "content": "export const foo = 1;" },
      tool_output: "File written successfully."
    }
  })
});

```

The `Observer` function in [`src/functions/observe.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/functions/observe.ts) processes this payload (checking `hookType` at lines 101–102) and stores it as a `RawObservation` entry defined in [`src/types.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/types.ts) (lines 15–24).

## Code Implementation Details

Key implementation files reveal the architectural separation between these hooks:

- **[`src/hooks/pre-tool-use.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/hooks/pre-tool-use.ts)**: Handles conditional logic for context injection. Lines 34–37 implement the early-exit guard, while lines 90–94 handle the stdout output that Claude Code consumes.

- **[`src/hooks/post-tool-use.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/hooks/post-tool-use.ts)**: Implements mandatory observation capture. The `extractImageData` helper (lines 60–88) handles base64 image extraction, and the truncation logic (lines 93–101) ensures outputs stay within the 8,000-character limit.

- **[`src/replay/jsonl-parser.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/replay/jsonl-parser.ts)**: Distinguishes between hook types during replay generation, mapping `post_tool_use` entries at line 118 and `pre_tool_use` entries at line 156 to timeline events.

- **[`src/triggers/api.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/triggers/api.ts)**: Registers both the `/enrich` endpoint (for PreToolUse) and `/observe` endpoint (for PostToolUse) that the hooks call via REST.

## Summary

- **PreToolUse hooks** run before tool execution to optionally inject context into the model's input stream, requiring `AGENTMEMORY_INJECT_CONTEXT=true` to activate.
- **PostToolUse hooks** run after tool completion to permanently store tool outputs, images, and metadata, and cannot be disabled.
- PreToolUse communicates via `stdout` to influence the immediate model turn, while PostToolUse persists data via `/agentmemory/observe` for long-term retrieval.
- The `hookType` field distinguishes these observations in the storage layer ([`src/functions/observe.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/functions/observe.ts) line 101) and replay parser ([`src/replay/jsonl-parser.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/replay/jsonl-parser.ts)).

## Frequently Asked Questions

### Can I disable PostToolUse hooks to reduce overhead?

No. According to the source code in [`src/hooks/post-tool-use.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/hooks/post-tool-use.ts), PostToolUse hooks are always active in the capture pipeline. Unlike PreToolUse hooks, there is no environment variable to disable them because AgentMemory depends on these observations for core functionality like session replay and audit logging.

### Why is PreToolUse disabled by default?

PreToolUse is disabled by default because it increases token consumption. When `AGENTMEMORY_INJECT_CONTEXT` is enabled, the hook retrieves contextual snippets from the AgentMemory server and injects them into the model's context window (lines 90–94 in [`src/hooks/pre-tool-use.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/hooks/pre-tool-use.ts)). This enrichment improves model accuracy but costs additional tokens per turn.

### How does AgentMemory handle large tool outputs in PostToolUse?

The PostToolUse hook implements automatic truncation. In [`src/hooks/post-tool-use.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/hooks/post-tool-use.ts) (lines 93–101), the `truncate` function limits `tool_output` to 8,000 characters before sending the payload to `/agentmemory/observe`. This prevents storage bloat while preserving the essential content of filesystem operations.

### Can PreToolUse and PostToolUse hooks be used together?

Yes. They serve complementary purposes in the capture pipeline. PreToolUse enriches the model's input before execution (when enabled), while PostToolUse records the result after execution (always). During replay, [`src/replay/jsonl-parser.ts`](https://github.com/rohitg00/agentmemory/blob/main/src/replay/jsonl-parser.ts) processes both hook types—`post_tool_use` at line 118 and `pre_tool_use` at line 156—to reconstruct the full session timeline.