Putting it all together
This final chapter traces the complete path of a user request through the system, from keystroke to completed turn, touching every layer we’ve covered.
This is the payoff chapter. Every type, trait, and design decision from the previous 22 chapters appears here in context. If something below is unfamiliar, the cross-reference tells you where to look.
The scenario
A user types: “Add error handling to the parse function in src/parser.rs”
The agent is configured with filesystem tools, shell tools, a PathPolicy for the workspace, a CommandPolicy with cargo in the allowlist, ForegroundThenDetachAfter(10s) for shell commands, a KeepRecentStrategy compaction pipeline, and a CompositeReporter writing to stdout and a usage tracker.
What happens
1. Input submission
The CLI reads the user’s message and submits it as a User item:
#![allow(unused)]
fn main() {
driver.submit_input(vec![Item {
kind: ItemKind::User,
parts: vec![Part::Text(TextPart { text: user_input, .. })],
..
}])?;
}
2. Compaction check
The driver checks the compaction trigger. If the transcript exceeds the configured threshold, the compaction pipeline runs — dropping old reasoning blocks, trimming failed tool results, keeping recent items.
3. Turn construction
The driver builds a TurnRequest containing:
- The working transcript (system prompt, context items, conversation history)
- Tool specs from the registry (fs.read_file, fs.write_file, fs.replace_in_file, shell.exec, etc.)
- The normalized prompt cache request for the turn
4. Model invocation
The adapter serializes the request and sends it to the provider. The response streams back as SSE chunks.
5. First tool call — read the file
The model decides it needs to see the file first. It emits a ToolCallPart:
{ "name": "fs.read_file", "input": { "path": "src/parser.rs" } }
The driver:
- Looks up
fs.read_filein the registry - Evaluates the
FileSystemPermissionRequest::Readagainst the permission checker - The
PathPolicyallows reads under the workspace root →Allow - Executes the tool
FileSystemToolResourcesrecords thatsrc/parser.rshas been read- Appends the
ToolResultPartto the transcript
6. Automatic roundtrip
The driver starts another model turn with the updated transcript. The model now has the file contents.
7. Second tool call — edit the file
The model emits a fs.replace_in_file call with the old and new text.
The driver:
- Evaluates
FileSystemPermissionRequest::Editforsrc/parser.rs - Checks read-before-write policy → the file was read in step 5 →
Allow - Executes the replacement
- Appends the result
8. Third tool call — verify the change
The model runs shell.exec with cargo check:
The driver:
- Evaluates the
ShellPermissionRequest CommandPolicyhascargoin the allowlist →Allow- The task manager routes it as
ForegroundThenDetachAfter(10s) - The command finishes in 3 seconds → result returned immediately
- Appends the result
9. Final response
The model sees the successful build output and produces a text response explaining what it changed. The StdoutReporter streams each text chunk to the terminal as it arrives.
10. Turn completion
The model finishes with FinishReason::Completed. The driver returns LoopStep::Finished(TurnResult). The CLI displays the usage summary and waits for the next user input.
The dependency graph in action
User input
│
▼
agentkit-core ──────────── Item, Part, Delta, Usage, FinishReason, identifiers
│
▼
agentkit-loop ──────────── LoopDriver, TurnRequest, LoopStep, AgentEvent
│
├── agentkit-compaction ─ CompactionTrigger, CompactionPipeline
│ (fires before step 3, trims old items)
│
├── agentkit-provider-* ─ ModelAdapter → ModelSession → ModelTurn
│ (step 4, sends transcript, streams response)
│
├── agentkit-tools-core ─ ToolExecutor, PermissionChecker
│ │ (step 6, preflight + execute)
│ │
│ ├── agentkit-tool-fs ── ReadFileTool, ReplaceInFileTool
│ │ (steps 5, 7)
│ │
│ └── agentkit-tool-shell ─ ShellExecTool
│ (step 8)
│
├── agentkit-task-manager ── AsyncTaskManager, routing
│ (step 8, ForegroundThenDetachAfter)
│
└── agentkit-reporting ──── StdoutReporter, UsageReporter
(every step, event delivery)
Every crate has a clear, narrow responsibility. The loop coordinates. Tools execute. Permissions gate. Reporters observe. The host decides.
Cross-reference
Each step in the walkthrough above maps to a chapter:
| Step | Chapter |
|---|---|
| 1. Input submission | Ch 6: Driving the loop |
| 2. Compaction check | Ch 16: Transcript compaction |
| 3. Turn construction | Ch 5: The model adapter boundary, Ch 15: Prompt caching |
| 4. Model invocation | Ch 1: Talking to models, Ch 4: Streaming |
| 5. Tool call (read) | Ch 11: Filesystem tools |
| 6. Permission check | Ch 10: Permissions |
| 7. Tool call (edit) | Ch 11: Filesystem tools |
| 8. Tool call (shell) | Ch 12: Shell execution, Ch 18: Task management |
| 9. Streaming text | Ch 4: Streaming and deltas, Ch 19: Reporting |
| 10. Turn completion | Ch 6: Driving the loop |
Where to go from here
This book has covered the full architecture of an agent system. Some areas for further exploration:
- Custom providers — implement adapters for Anthropic, Google, or local model servers using either
CompletionsProvider(~50 lines) or the raw traits (~200-500 lines) - Custom tools — database queries, API integrations, code analysis, deployment automation
- MCP servers — connect to external tool providers for GitHub, databases, Slack, etc.
- Advanced compaction — semantic summarization with a nested agent backend
- Multi-agent patterns — tools that spawn sub-agents, parallel agent execution, orchestrator/worker architectures
- Production hardening — retry strategies, rate limiting, cost controls, audit logging, persistent sessions
The agentkit crate ecosystem is designed to grow at the edges. The core loop and data model are stable foundations. New tools, providers, and integration patterns can be added without changing the architecture.
| Stable (change rarely) | Grows (add freely) |
|---|---|
agentkit-core types | agentkit-provider-* crates |
ModelAdapter / ModelSession traits | agentkit-tool-* crates |
LoopDriver / LoopStep | CompactionStrategy implementations |
Tool / ToolSpec / ToolRegistry | LoopObserver implementations |
PermissionChecker / PermissionPolicy | Custom ContextSource implementations |
Delta protocol | MCP server integrations |
Example: The
examples/directory in the agentkit repository contains working implementations that exercise every concept in this book, from the simplest chat loop to a full multi-tool coding agent.