AFK’s architecture is built on one principle: orchestration and execution are separate concerns. The runner (orchestration) manages the step loop, state, and policies. Adapters (execution) handle LLM calls, tool execution, and external communication. You can swap any adapter without touching your agent code.Documentation Index
Fetch the complete documentation index at: https://afk.arpan.sh/llms.txt
Use this file to discover all available pages before exploring further.
Layered architecture
Module boundaries
| Module | Responsibility | Dependencies |
|---|---|---|
afk.agents | Agent definition, configuration, fail-safe | pydantic |
afk.core | Runner, step loop, state management, policies | afk.agents, afk.llms, afk.tools, afk.memory |
afk.llms | LLM runtime, provider adapters, retry/circuit breaking | Provider SDKs |
afk.tools | Tool registry, execution, validation, hooks | pydantic |
afk.memory | State persistence, checkpoints, compaction | Backend drivers |
afk.observability | Event pipeline, metrics, exporters | OTEL SDK (optional) |
afk.messaging | Public A2A protocol, auth, host, and delivery exports | afk.agents |
afk.evals | Eval runner, assertions, reporting | afk.core |
Key rule: Modules in the Adapters layer never import from each other.
afk.llms doesn’t know about afk.tools. Only afk.core wires them
together.Runtime sequence
What happens when you callrunner.run(agent, user_message="..."):
Contract boundaries
Every boundary between modules uses a typed contract: All contracts are Pydantic models. This means:- Validation at boundaries — malformed data causes clear errors
- Serializable — every contract can be logged, stored, or sent over the wire
- Versionable — contracts have stable shapes for backward compatibility
Error isolation
Failures in one adapter don’t crash the others:| Failure | Impact | Runner behavior |
|---|---|---|
| LLM call fails | No response for this step | Retry (if retryable) or fail the run |
| Tool execution fails | Tool result is an error object | Return error to LLM for self-correction |
| Memory backend fails | State not persisted | Run continues (degraded mode) |
| Telemetry fails | Events not exported | Run continues (events dropped silently) |
Design principles
- Contracts first. Define the interface (Pydantic model), then implement the behavior. Never skip the contract.
- No cross-adapter imports.
afk.llmsdoesn’t importafk.tools. Onlyafk.corewires modules together. - Classify failures. Every error is retryable, terminal, or non-fatal. The runner uses this classification to decide what to do.
- Least privilege. Adapters get only the data they need. LLM adapters don’t see tool results until the runner decides to include them.
Next steps
LLM Layer
Provider-portable LLM runtime in detail.
Developer Guide
Contribute to AFK — patterns and conventions.