A low-level, async-first framework for building AI agents in Python.
Docs · Quickstart · Examples · Changelog
agentkit is a framework, not an agent library. It gives you the primitives
to build your own agent — an Agent class, a Cognition strategy, a Ctx
that threads services + budgets + cancel through every call, a middleware
chain you compose yourself, and typed value types the whole stack shares.
What it does with an LLM, what tools it exposes, what it stores, when it
stops — every one of those decisions is yours.
It is not a batteries-included agent (no built-in personas, no bundled prompts, no opinionated stack pushing you toward one vendor). It is not a chain-builder or a graph DSL either. If you want scaffolding that hides the loop, use one of those; agentkit hands you the loop and gets out of the way.
Use agentkit when you want an agent runtime whose seams are visible, whose
types survive mypy --strict, whose core has zero runtime dependencies,
and whose control plane (cancel, budget, retry, HITL suspend/resume) is
first-class instead of tacked on. Used in production at Arc Labs.
pip install arc-agentkitRequires Python 3.12+. The core has no runtime dependencies. Concrete adapters live behind optional extras — install only what you use:
pip install "arc-agentkit[http]" # httpx-based LLM providers (OpenAI, Anthropic, DeepSeek, ...)
pip install "arc-agentkit[postgres]" # Postgres checkpoint store + pgvector memory
pip install "arc-agentkit[redis]" # Redis-backed store
pip install "arc-agentkit[observability]" # OpenTelemetry metrics + tracing exporters
pip install "arc-agentkit[fast]" # orjson for hot-path JSONDefine an agent, invoke it via a Ctx bound to a fake LLM, get a typed
AgentResult:
import asyncio
from agentkit import Agent
from agentkit.testing import FakeLLM, make_test_ctx
async def main() -> None:
ctx = make_test_ctx(llm=FakeLLM("42"))
agent = Agent(
name="answerer",
model="gpt-4o-mini",
prompt="Answer the question in as few words as possible.",
)
result = await agent.run("what is 6 * 7?", ctx)
print(result.output) # -> "42"
print(result.usage) # -> Usage(input_tokens=10, output_tokens=5, cost_usd=0.0001, cache_read_tokens=0, cache_write_tokens=0)
if __name__ == "__main__":
asyncio.run(main())Point the same code at a real provider by using the batteries-included
claude chat directly:
from agentkit import claude
async with claude(api_key="sk-...", model="claude-sonnet-4-6") as chat:
result = await chat("what is 6 * 7?", system="Answer in as few words as possible.")
print(result.content)More runnable examples — tool loops, streaming, composed middlewares —
under examples/.
Five layers, one direction of dependency. Each is a link into the docs where depth lives:
- Kernel — opinion-free
primitives: immutable value types (
Message,ToolCall,LLMResult,Usage), the port Protocols every seam (LLMPort,StorePort,VectorPort, …) implements, the middleware contract, and concurrency + resilience helpers. Zero third-party imports. - Runtime —
RunContext(identity + services + cancel + budget),Invoker(the one runner that walks the middleware chain to a terminal LLM/tool call),BudgetandQuota(spend meters that halt runs cleanly on overrun). - Agent + Cognition —
Agentis identity + chat-call config;Cognitionis the pluggable turn-taking strategy. Ships withSingleCallCognition,ReActCognition(tool loop + HITL suspend + durable resume), andCoordinatorCognition(multi-agent orchestration). Adding a new regime is one Protocol impl — noAgentsubclassing. - Middleware —
cross-cutting concerns as composable functions:
tracing,retry,fallback,memoize,output_coerce,meter,compaction,egress,audit,security. Two ordered lists (chat + tool) handed toInvoker; reorder or swap by editing the list. - Capabilities —
optional cross-cutting collaborators:
RequestBuilder(prompt + grounding),Compactor(four strategies),Guardrail,Evaluator,Checkpointer,SchemaAdapter(structured outputs across Pydantic, attrs, dataclass, or raw JSON Schema).
The bet: every seam is a typed Protocol injected at wire-up, so the loop
stays legible and unit-testable, and swapping a backend never edits the loop.
- Zero runtime dependencies in the core. Install
arc-agentkitalone and you have a working framework — nopydantic, nohttpx, no vendor SDK. Extras (http,postgres,redis,observability) are opt-in. - Ports and adapters, all the way down. Every I/O seam is a
Protocol. Swap the LLM, the store, the vector DB, the checkpointer, the tracer, the metrics port — the loop doesn't move. - Typed public surface,
mypy --strictclean. Every re-exported name inagentkitcarries full type information.py.typedships in the wheel. Frozen dataclasses for the value layer. - Human-in-the-loop is a real pause. A gated agent suspends to a
checkpoint; a fresh worker (potentially in a new process, weeks later)
can
resume(run_id, decisions)and continue. No in-memory state, no polling. - Cost you can trust.
Budgetcharges every LLM call under a lock; totals are invariant under concurrent workers. Hit the ceiling and the run stops with aMeterExceeded, not silently over-spends. - A first-class testing kit.
FakeLLM,FakeFetch,FakeSearch,FakeMemory,FakeTool, plusmake_test_ctx()— the same doubles the framework's own suite uses. Zero API keys required to unit-test your agents end to end.
- You want a graph DSL that draws the flow for you — reach for LangGraph.
- You want a batteries-included agent product (built-in personas, hosted memory, one-click deploy) — reach for a hosted framework.
- You want to prototype in a notebook and never leave — anything works; agentkit's benefits (typed seams, cancel/budget, checkpointing) only pay off when the code has to survive production.
- Site: arc-labs-ai.github.io/agentkit
- Examples:
examples/— runnable, no API keys required. - Mental models:
docs/mental-models/— four end-to-end use cases with narrative walkthroughs of internal state at each step (multi-tenant chat with docs, autonomous DevOps investigator, long-running data enrichment, coordinated multi-agent research). - Changelog:
CHANGELOG.md.
Contributions are welcome. See CONTRIBUTING.md for the
development setup, coding conventions (ruff + mypy --strict + pytest
must all pass), and the PR checklist.
Quick local loop:
git clone https://github.com/arc-labs-ai/agentkit
cd agentkit
uv sync # install deps + dev group
uv run pytest # full test suite
uv run mypy agentkit # strict typecheck
uv run ruff check . # lintApache License 2.0 — see LICENSE and NOTICE.
Copyright (c) Arc Labs.