← Learning paths
claude/advanced

State management

Externalizing workflow state to disk so long-running orchestrations survive context compaction β€” execution tracking, post-compaction recovery via hooks, and session handoffs.

πŸ“ Wholesale AI Champions ⏱ 8 min read πŸ“š Team workflows

Long orchestration workflows will hit context compaction β€” Claude’s conversation gets compressed to free up space. If your workflow state only exists in the conversation, it gets lost.

The solution: externalize state to disk.


What to persist

StateWhere to write itWhy
Task progress.executions/{id}.mdKnow which tasks are done after compaction
Decisions made.context/{id}/decisions.mdDon’t re-debate settled questions
Lessons learned.reflections/{id}.mdPrevent repeating mistakes
Session handoff.handoffs/{id}-{timestamp}.mdResume in a new conversation

Execution tracking format

The adesa-workflow plugin uses an append-only markdown file per story:

# Execution: Story 12345 - Add caching layer
## Status
Started: 2026-04-07T10:30:00Z
Phase: implementation
## Repos
- [x] api-service - commit: abc1234 (confidence: high)
- [x] config-service - commit: def5678 (confidence: medium)
- [ ] frontend-app
## Decision Log
### D1: Used Redis instead of in-memory cache
- Reason: Multiple replicas need shared state
- Considered: In-memory with sticky sessions
- Confidence: high
## Gotchas
- Redis connection string must use SSL endpoint in production

The format is designed to be append-only β€” new decisions and status updates are added at the bottom, never overwriting previous entries. This makes it safe for multiple agents to write to the same file without coordination.


Post-compaction recovery

Both adesa-workflow and essentials use a hook to detect when context compaction has occurred and automatically re-inject critical state.

How it works in adesa-workflow: A PostToolUse hook (hooks/post-tool-use.js) fires after every tool call. It monitors the context usage percentage β€” when it detects a significant drop, it reads the execution tracking file (.executions/{story-id}.md) and injects the first ~2,000 characters back into the conversation as a system reminder. This keeps Claude aware of which tasks are done, which decisions were made, and which repos are in progress.

How it works in essentials: Both essentials-execute and essentials-swarm monitor session health (message count, elapsed time, response quality). When thresholds are hit, they pause execution, checkpoint state to ai_docs/, and run the essentials-whats-next skill to generate a handoff document. The user starts a fresh session with the checkpoint attached.

The two approaches solve the same problem differently:

ApproachUsed byRecoveryUser action needed
Auto re-injectadesa-workflowHook silently re-injects state after compactionNone β€” transparent
Checkpoint and restartessentialsPause, save state, prompt user to start freshStart new session with checkpoint

Session handoffs

Conversations have a limited lifespan. Context compaction buys time, but eventually you need to start fresh β€” end of day, switching tasks, or the session is just too long. Session handoffs capture everything the next conversation needs to continue seamlessly.

How it works in adesa-workflow: The /aw-handoff skill captures the current skill phase, affected repos and their branch/commit state, decisions made during the session, open questions, and gotchas. It commits any WIP work in the repos, then writes everything to .handoffs/{work-item-id}-{timestamp}.md. In the next session, /aw automatically detects the handoff file and offers to resume from where you left off.

How it works in essentials: The /essentials-whats-next skill generates a zero-loss context handoff document at ai_docs/whats-next.md. It captures completed tasks, in-progress work, blocking issues, and next steps. The user attaches this file when starting a new session.

ApproachUsed byResume triggerFile location
Auto-detectadesa-workflow/aw detects handoff files on startup.handoffs/{id}-{timestamp}.md
Manual attachessentialsUser attaches file to new sessionai_docs/whats-next.md

Implementing your own handoff

A handoff file should capture everything Claude needs to continue without re-reading the entire codebase. At minimum:

# Handoff: Story 12345 - 2026-04-07T14:30:00Z
## Current Phase
implementation - executing Wave 2
## Completed
- repo-a: commit abc1234
- repo-b: commit def5678
## In Progress
- repo-c: DI wiring done, tests remaining
## Decisions Made
- D1: Used Redis instead of in-memory cache (multiple replicas need shared state)
## Open Questions
- Should the cache TTL be configurable per-tenant?
## Gotchas for Next Session
- EF Core requires explicit Include() for navigation properties
- Redis connection string must use SSL endpoint in production

To build this into your own skill:

  1. Write a handoff skill that gathers state from your execution tracking files, git status across repos, and any in-memory decisions from the current conversation
  2. Commit WIP work before writing the handoff β€” uncommitted changes in repos won’t survive if the user switches branches
  3. Write to a predictable location so the resume skill can find it (e.g., .handoffs/ or ai_docs/)
  4. Build a resume check into your entry-point skill β€” on startup, glob for handoff files and offer to continue if one exists

Handoff files are snapshots, not live state. If someone else pushes changes to a repo between sessions, the handoff may be stale. Your resume skill should verify git state (branch exists, no conflicts) before blindly continuing.


State architecture example

Here’s the full disk layout used by adesa-workflow:

planning-repo/
β”œβ”€β”€ repos.json # Team's repo registry
β”œβ”€β”€ features/
β”‚ └── {feature-id}/
β”‚ β”œβ”€β”€ feature-overview.md # High-level feature description
β”‚ └── stories/
β”‚ β”œβ”€β”€ {story}.md # Business-focused story
β”‚ └── {story}.impl.md # Technical spec per repo
β”œβ”€β”€ .context/{id}/
β”‚ β”œβ”€β”€ discovery.md # Research notes
β”‚ └── decisions.md # Settled questions
β”œβ”€β”€ .executions/{story-id}.md # Progress tracking (append-only)
β”œβ”€β”€ .reflections/{story-id}.md # Lessons learned
└── .handoffs/{id}-{timestamp}.md # Session resume state

Every piece of state lives on disk. When context compaction hits, hooks re-inject the execution tracking. When a session ends, handoff files save everything needed to resume. When a new feature starts, reflections load as guardrails.