Persistent Agent Sessions

How Claude Code adapter sessions maintain conversational context across heartbeat cycles, when and how to reset session state, and the tradeoff between continuity and drift.

Persistent Agent Sessions

What you'll learn

What persistent sessions are, how they differ from stateless invocations, and when to use them for agents that need memory across tasks.

Stateless vs Persistent

By default, every heartbeat invocation is stateless: the agent receives the system prompt + task description, returns an answer, and forgets everything. The next invocation starts fresh.

Persistent sessions maintain conversation history across invocations. The agent remembers what it did before — useful for agents that build on previous work.

When to Use Persistent Sessions

Stateless (default) Persistent session
Independent research tasks Long-running project work
Classification / labelling Code reviews across multiple PRs
Content generation Ongoing customer interactions
High volume, low cost Lower volume, context-rich

Enabling Persistent Sessions

In adapter_config:

{
  "adapter_type": "claude-code",
  "adapter_config": {
    "model": "claude-opus-4-5",
    "session_mode": "persistent",
    "session_ttl_hours": 24
  }
}

With session_mode = 'persistent', Paperclip:
1. Creates a session ID on first invocation
2. Stores the conversation history in the database (or in-memory for sandbox)
3. Passes prior turns as context on subsequent invocations
4. Expires the session after session_ttl_hours of inactivity

Session Storage

For claude-code persistent sessions, history is stored in:

Sandbox (PGlite):

.paperclip/sessions/{agent_id}/{session_id}.json

Production (PostgreSQL):

CREATE TABLE agent_sessions (
  id         uuid PRIMARY KEY,
  agent_id   uuid NOT NULL REFERENCES agents(id),
  company_id uuid NOT NULL,
  history    jsonb NOT NULL DEFAULT '[]',
  created_at timestamptz DEFAULT now(),
  last_used  timestamptz DEFAULT now(),
  expires_at timestamptz
);

Viewing Session History

# Via API
curl http://localhost:3100/api/companies/${COMPANY_ID}/agents/${AGENT_ID}/sessions

# Response:
{
  "sessions": [{
    "id": "sess_...",
    "message_count": 12,
    "created_at": "...",
    "last_used": "...",
    "expires_at": "..."
  }]
}

Clearing a Session

When you want the agent to start fresh (e.g. after a project phase ends):

curl -X DELETE \
  http://localhost:3100/api/companies/${COMPANY_ID}/agents/${AGENT_ID}/sessions/${SESSION_ID}

Token Budget Considerations

Persistent sessions increase token consumption because prior turns count as input tokens. Monitor with:

SELECT
  date_trunc('day', ce.created_at) AS day,
  SUM(ce.input_tokens)  AS total_input,
  SUM(ce.output_tokens) AS total_output,
  SUM(ce.cost_usd)      AS daily_cost
FROM cost_events ce
WHERE ce.agent_id = 'your-agent-id'
GROUP BY day
ORDER BY day DESC;

If input tokens grow linearly each day, the session context window is accumulating history. Set a lower session_ttl_hours or implement context summarization.

Checkpoint ✓

Sign in for progress tracking & Q&A →