Agentic Pipeline Design Guidelines
Agentic Pipeline Design Guidelines
Derived from analysis of Claude Code’s architecture by Nate Jones, with additional primitives addressing memory, error recovery, human handoff, observability, testing, and inter-agent communication. Ordered by implementation priority.
Meta-Principles
Apply these throughout. They are not a separate phase.
- 80/20 rule. Building agents is 80% non-glamorous plumbing and 20% AI. The boring infrastructure is what makes it work at scale.
- Bias toward simplicity. Start with single-agent design. Only add multi-agent coordination when you have concrete reasons. Premature complexity is where most projects die.
- Assume failure. Every design decision should account for crashes, token overruns, permission violations, and partial execution.
- Engineering over novelty. This is fundamentally good back-end engineering applied to agentic pipelines. The principles are not new. The domain is.
Tier 1: Day-One Non-Negotiables
Build these before shipping anything.
1. Tool Registry with Metadata-First Design
Define all agent capabilities as a data structure before writing implementation code. The registry answers “what exists and what does it do” without executing anything.
- Implement a
listTools()function that returns metadata (name, description, source, category) for all capabilities. No side effects on invocation. - Support runtime filtering so the agent loads only contextually relevant tools per run.
- Write the registry before any model-facing orchestration code. It is the foundation everything else builds on.
Claude Code reference: Two parallel registries (207 command entries for users, 184 tool entries for the model), each carrying name, source hint, and responsibility description. Implementations load on demand.
2. Tiered Permission System
Not all tools carry the same risk. Categorize risk and apply different approval tiers per category.
- Pre-classify every action: read-only, mutating, potentially destructive.
- Define trust tiers: built-in (always available, highest trust), plug-in (medium trust, can be disabled), user-defined/skills (lowest trust by default).
- For shell/code execution: build layered security covering pre-approved command patterns, destructive command detection, domain-specific safety checks, and sandbox termination.
- Log every permission decision (granted or denied) with enough context to replay it.
Claude Code reference: The bash tool alone has an 18-module security architecture. Three separate permission handlers serve different contexts: interactive (human-in-the-loop), coordinator (multi-agent orchestration), and swarm worker (autonomous execution).
3. Human-Agent Handoff Protocols
Distinct from permissions. Permissions govern whether an action is allowed. Handoff governs when the agent should stop and return control to the human.
- Define explicit triggers for handoff: low confidence, ambiguous requirements, judgment calls outside the agent’s domain, conflicting constraints.
- Support multiple handoff modes: escalate and block (wait for human input), escalate with deadline (continue provisionally if no response), continue with flag (make a provisional decision, mark it for review), halt entirely.
- For background or scheduled agents, handoff requires a notification mechanism. The agent cannot simply stop and wait for terminal input.
- Log every handoff with the agent’s reasoning for escalating.
Design note: In interactive sessions, Claude Code handles this implicitly by outputting text without calling a tool, which stops the agentic loop. For non-interactive agents, handoff must be an explicit protocol, not an emergent behavior.
4. Session Persistence That Survives Crashes
An agent session is not just conversation history. It is a recoverable state object that includes conversation, usage metrics, permission decisions, and configuration.
- Design a session state structure that captures everything needed to resume.
- Persist after every significant event, not just at shutdown.
- Build a
resumeSession()function that reconstructs full agentic state, not just conversation history.
Claude Code reference: Sessions persist as JSON files capturing session ID, messages, and token usage (in/out). The query engine can be fully reconstructed from a stored session via load, reconstruct transcript, restore counters.
5. Workflow State (Separate from Session State)
A chat transcript answers “what have we said.” A workflow state answers “what step are we in, what side effects have occurred, is this safe to retry, and what happens after restart.”
- Model long-running work as explicit states:
planned,awaiting_approval,executing,awaiting_external,completed,failed. - Persist state checkpoints continuously. Be paranoid about crash recovery.
- Ensure the agent knows whether retrying a step is safe (idempotency awareness).
Key distinction: Session state and workflow state solve different problems. Almost every agentic framework conflates them. Without workflow state, you can restore where the agent was but not where the work was.
6. Error Recovery Semantics
Knowing that a step failed is not enough. The agent needs to know how to recover based on the side-effect profile of the failed operation.
- Classify every tool’s side-effect profile in the tool registry metadata: pure (no side effects), idempotent (safe to retry), non-idempotent (retry may cause duplication or corruption).
- Implement three recovery strategies and select based on classification:
- Retry: The operation had no side effects, or its side effects are idempotent. Safe to re-run.
- Rollback and retry: The operation partially completed and left inconsistent state. Execute compensating actions before retrying.
- Skip and continue: The failure does not block downstream work. Log it, flag it for human review, move on.
- Define compensating actions for non-idempotent operations at registration time, not at failure time.
- Surface recovery decisions in the system event log.
- Note that some failures are not observable at execution time. An operation may return success while producing output that is fabricated or wrong (see #11). Treat external grounding checks as a failure detector that can re-classify a “successful” step as failed and trigger the same recovery strategies.
Design note: Security and error recovery are different problems. Security asks “should this action be allowed.” Error recovery asks “this allowed action failed halfway through, now what.”
7. Token Budgeting with Hard Stops
Define hard limits on token usage. Track projected consumption every turn. Stop execution with a structured reason before exceeding the budget. Do not discover overruns after the fact.
- Set max turns per conversation, max token budget per conversation, and a compaction threshold.
- Calculate projected token usage each turn; halt gracefully if the projection exceeds the budget.
- Expose usage metrics (input tokens, output tokens, remaining budget) to both the agent and the user.
8. Structured Streaming Events
Every streaming event is an opportunity to communicate system state. The stream should convey what tools the agent is considering, how many tokens are consumed, and whether the agent is wrapping up.
- Define a typed event schema (e.g.,
message_start,tool_match,command_match,crash_reason). - Include a crash event type: if the stream terminates abnormally, the last event should carry a reason. This is the agent’s black box.
- Design events to be human-readable so users can intervene when the agent goes off track.
9. System Event Logging
Separate from streaming events and conversation. A structured log of what the agent did, not just what it said.
- Log: context loaded, registry initialization, routing decisions, execution counts, permission decisions, handoff decisions, recovery actions.
- Every event should carry a category and structured details sufficient to reconstruct an agentic run.
- This is non-negotiable for any agent operating in a production environment.
10. Two-Level Verification
Level 1: Verify agent work. After each run, the agent checks its own output against defined criteria.
Level 2: Verify harness changes. When you modify the agentic harness itself, run verification tests to confirm invariants still hold. Examples: Do destructive tools still require approval? Does the agent gracefully stop when tokens run out? Are permission boundaries intact?
Name these tests. Log them. The harness will evolve; your guardrails must evolve with it.
Design note: Both levels here check behavior and structure. For factual claims with external referents — citations, DOIs, file paths, API signatures, quotes — behavioral verification is insufficient because the failure mode is confident, well-formed output that does not correspond to reality. See #11.
11. Referent Grounding for Factual Claims
Any output containing a claim with an external referent — citation, DOI, URL, API signature, file path, statistic, direct quote, identifier — must be verified against an authoritative source before reaching the user. This is distinct from verification (#10), which checks behavior; grounding checks correspondence to reality.
- Classify output types in the tool registry: claims with external referents must be tagged as “grounding-required.”
- Define an authoritative source per referent type: Crossref or OpenAlex for citations, the actual filesystem for paths, the actual API spec for signatures, the source document for quotes.
- Grounding is a deterministic round-trip, not an LLM judgment. Resolve the DOI. Stat the file. Diff the quote. Do not ask a model whether the citation is real.
- On grounding failure: strip the claim, flag it for human review (#3), or block the output. Never silently emit unverified referents.
- Log every grounding check in the system event log (#9).
Design note: This addresses the “Frankenstein citation” failure mode documented in the 2025–26 scientific literature, where LLMs assemble plausible references from real fragments — correct authors, real journal, wrong title, or real title with a fabricated DOI. The model is not uncertain; it is confidently wrong. Confidence calibration cannot fix this. Only external grounding can.
Tier 2: Operational Maturity
Build these as the system scales in complexity, session count, or agent count.
12. Dynamic Tool Pool Assembly
A general-purpose agent should not load all tools on every run. Assemble a session-specific tool pool based on mode flags, permission context, and deny lists.
- Let the agent read from a wider tool set and select what it needs for a given run.
- Avoid hard-coding tool sets per workflow. Allow dynamic assembly for general-purpose agents.
13. Transcript Compaction
Conversation history is token-expensive. Compact it automatically after a configurable number of turns.
- Keep recent entries; discard older ones.
- Preserve the original instruction that started the agent.
- Track whether compacted state has been persisted to avoid data loss.
- Know what you’re keeping, why you’re keeping it, and how to verify it’s correct.
14. Memory Architecture
Compaction manages what fits in the context window. Memory manages what the agent knows across sessions.
- For session-scoped agents (e.g., a coding session with a clear start and end), compaction alone may suffice. For agents that persist across sessions, days, or weeks, structured memory is required.
- Define what to remember: decisions made, user preferences, domain context, outcomes of previous runs.
- Define how to index it: by topic, by recency, by relevance to the current task.
- Define when to surface it: at session start, on-demand via retrieval, or triggered by context similarity.
- Treat memory as a separate subsystem from conversation history. They serve different purposes and have different retention policies.
Design note: Claude Code does not implement a structured memory system. It works because coding sessions have natural boundaries. Agents with longer operational horizons need an explicit memory layer.
15. Observability and Debugging
System event logging (Tier 1, primitive 9) is the foundation. Observability is the analysis layer built on top of it.
- Trace visualization: reconstruct what happened across a multi-step run as a single navigable trace.
- Cost attribution: which steps consumed what tokens and wall-clock time.
- Performance profiling: which tool calls are slow, which are failing frequently.
- Anomaly detection: flag runs that deviate from expected patterns (e.g., 47 steps for a task that usually takes 12).
- Observability is fundamentally a post-hoc analysis problem. Streaming events give real-time visibility; observability gives historical and cross-run visibility.
16. Permission Audit Trail as First-Class Object
Permissions are not a boolean gate. They are queryable state.
- Build permission handlers appropriate to your execution contexts (human-in-the-loop, orchestrator-managed, autonomous).
- Make permission state easy to query and audit at any time.
17. Testing Non-Deterministic Systems
Two-level verification (Tier 1, primitive 10) covers individual runs and harness changes. This primitive covers regression testing for systems whose behavior varies with each run.
- Define evaluation frameworks that check behavioral properties rather than exact execution traces.
- Use golden-path tests with fuzzy matching: the agent should achieve a specific outcome, but the path may vary.
- Apply statistical pass/fail criteria: a test passes if the agent succeeds N out of M runs, not just once.
- Test for behavioral drift over time, not just correctness on a single run.
Design note: This is an emerging area with no settled best practices. Having any testing story beyond “run it and see if the output looks right” puts you ahead of most implementations.
18. Typed Agent Roles
Define agent types with constrained capabilities. Each type gets its own prompt, allowed tools, and behavioral constraints.
- Example roles: explore (read-only), plan (no code execution), verify (checks work), guide (user-facing), general-purpose.
- Constrain roles sharply. An explore agent cannot edit files, a plan agent cannot execute code.
- Use typed roles to manage agent populations and their efficiency in multi-agent systems.
19. Inter-Agent Communication Protocols
Typed roles constrain what each agent can do. Communication protocols govern how agents coordinate.
- Define the format agents use to hand off work: structured task descriptions, shared context objects, expected output schemas.
- Implement progress signaling so the orchestrator can distinguish “agent is stuck” from “agent is still working.”
- Define failure signaling: how does an agent report that it cannot complete a task, and what information does it pass back?
- Specify context sharing rules: what context transfers between agents, what stays private to a session, and what gets summarized vs. passed verbatim.
Design note: Claude Code’s sub-agent dispatch is minimal by design. The main agent sends a prompt via a Task tool, and the sub-agent receives it as a user message with the same system prompt. Sub-agents cannot spawn further sub-agents. This simplicity works for bounded, well-defined subtasks. Open-ended multi-agent collaboration requires richer protocols.