AgentKit builds an agent from YAML into a normal OCI container image. The
container serves an OpenAI-compatible /v1 Chat Completions API, can own stdio
MCP tools, and keeps secret values out of the image.
Use AgentKit when you want to package an agent the same way you package any other container: build it with Docker, run it locally, push it to a registry, and deploy it anywhere containers run.
Experimental: AgentKit is still early. APIs, file formats, and runtime behavior may change as the project evolves. Feedback, issues, and PRs are welcome.
Create agentkitfile.yaml:
#syntax=ghcr.io/sozercan/agentkit/agentkit:latest
apiVersion: v1alpha1
kind: Agent
metadata:
name: url-summarizer
model:
provider: openai-compatible
baseURL: https://api.openai.com/v1
name: gpt-4o-mini
apiKeyEnv: OPENAI_API_KEY # env var name only; never the secret value
instructions: |
Summarize any URL the user gives you in three bullet points.
expose:
openai: trueBuild and run it:
docker buildx build . -f agentkitfile.yaml -t url-summarizer:latest --load
docker run --rm \
-p 127.0.0.1:8080:8080 \
-e AGENTKIT_BIND=0.0.0.0 \
-e AGENTKIT_AUTH_TOKEN=dev-token \
-e OPENAI_API_KEY="$OPENAI_API_KEY" \
url-summarizer:latestCall the agent:
curl http://127.0.0.1:8080/v1/chat/completions \
-H 'authorization: Bearer dev-token' \
-H 'content-type: application/json' \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"https://example.com"}]}'The image also exposes:
GET /healthzGET /v1/modelsPOST /v1/chat/completions
AgentKit is model-endpoint agnostic. model.baseURL can point at any
OpenAI-compatible /v1 endpoint: OpenAI, another hosted provider, a local
gateway, an in-cluster service, or a model image served by
AIKit. AIKit is only one example.
For an AIKit example, run any AIKit image that exposes the OpenAI-compatible API on a Docker network. This can be a prebuilt CPU/GPU image or a custom model image you create with AIKit:
docker network create agentkit-local 2>/dev/null || true
docker run -d --rm \
--name aikit-llama \
--network agentkit-local \
ghcr.io/kaito-project/aikit/llama3.2:1bThen point the Agentkitfile at that service and use the model name exposed by the
endpoint. No-auth local endpoints do not need apiKeyEnv unless you add your own
auth layer:
model:
provider: openai-compatible
baseURL: http://aikit-llama:8080/v1
name: llama-3.2-1b-instructFor any other endpoint, replace baseURL and model.name with the values for
that service. For another prebuilt or custom AIKit image, also replace the image
reference and container name.
Run the generated AgentKit container on the same Docker network so it can reach
aikit-llama. If AIKit is exposed through the host instead, use an address that
is reachable from inside the AgentKit container, such as
http://host.docker.internal:<port>/v1 on Docker Desktop.
Declare stdio MCP servers in tools:. Tool commands are started by the runtime
and are available to the agent, not supplied by each API request.
tools:
- name: fetch
command: ["uvx", "mcp-server-fetch"]
env: ["FETCH_TIMEOUT"]env entries are env var names that may be passed into that tool subprocess.
AgentKit does not pass the whole container environment to every tool.
Cold uvx or npx tools may download packages before speaking MCP, so first
boot can be slower than later boots. Tune the tool initialization timeout with:
docker run -e AGENTKIT_MCP_TIMEOUT=180 ...See docs/agentkitfile.md for the full Agentkitfile
schema.
AgentKit files are runtime-neutral. Pick the agent framework with the optional
runtime: field:
runtime: value |
Framework |
|---|---|
omitted / pydantic-ai |
pydantic-ai |
microsoft-agent-framework / maf |
Microsoft Agent Framework |
langgraph |
LangChain/LangGraph |
runtime: langgraphAll runtimes read the same built agent config and serve the same non-streaming
OpenAI-compatible API. See docs/runtime-adapters.md
for runtime behavior and adapter details.
By default, generated images bind to 127.0.0.1 inside the container. If you bind
to a non-loopback address such as 0.0.0.0, set AGENTKIT_AUTH_TOKEN; /v1/*
requests must then include Authorization: Bearer <token>.
docker run --rm \
-p 8080:8080 \
-e AGENTKIT_BIND=0.0.0.0 \
-e AGENTKIT_AUTH_TOKEN="$AGENTKIT_AUTH_TOKEN" \
-e OPENAI_API_KEY="$OPENAI_API_KEY" \
url-summarizer:latest/healthz remains unauthenticated for liveness checks.
The most important rules are:
-
apiVersion: v1alpha1andkind: Agentare required. -
Unknown YAML fields fail the build.
-
model.providermust beopenai-compatible. -
instructionscan be inline text or a file source:instructions: file: ./prompt.md
-
apiKeyEnvand toolenvvalues are env var names, not secret values. -
expose.openaimust betrue;expose.portdefaults to8080.
Full reference: docs/agentkitfile.md.
Build the frontend image, the default runtime adapter image, and a test agent:
make build-agentkit
make build-serve
make build-test-agent
make run-test-agentBuild a test agent for another runtime:
make build-serve-maf
make build-test-agent RUNTIME=maf
make build-serve-langgraph
make build-test-agent RUNTIME=langgraphSee docs/development.md for the full local test and CI
workflow.
docs/agentkitfile.md— Agentkitfile schema and build arguments.docs/runtime-adapters.md— runtime behavior, adapters, auth, request handling, and tool lifecycle.docs/agent-abi.md— built/agent/agent.yamlcontract.docs/development.md— local development and CI.docs/architecture.md— codebase architecture map for contributors.test/foundry-hosted-agent/README.md— Foundry Hosted Agents smoke-test wrapper.