Pupil is a CLI tool for building teachable AI agents that carry their knowledge as OCI container images. You define an agent with a pupil.yaml config file, give it curriculum (documents, URLs), build it into a container image, and distribute it through any OCI registry. The agent's knowledge lives inside the container. When you run the agent, it uses its learned memories to answer questions. When you push the image to a registry, the knowledge travels with it.
- Rust 1.85+ (for building from source)
- Docker or Podman
- An LLM API key for at least one supported provider (e.g.
ANTHROPIC_API_KEY,OPENAI_API_KEY,GOOGLE_API_KEY) - Embeddings: recalld needs an embedding provider. By default, Pupil uses Ollama with
embeddinggemma. If Ollama is running on your host, the build connects to it automatically. If not, the build starts an Ollama sidecar container (no local install needed). You can also configure recalld to use a different embedding provider.
Run pupil doctor after installation to verify your environment.
git clone https://github.com/calebevans/pupil.git
cd pupil
cargo install --path crates/pupil-cliThen build the base container image that all agents derive from:
docker build -t pupil-base:dev -f container/Dockerfile .# 1. Create a new agent project
pupil create my-agent
cd my-agent
# 2. Add curriculum content (local files or URLs)
pupil teach /path/to/docs/
pupil teach --url https://docs.example.com/guide
# 3. Build the agent (the LLM reads and learns the curriculum)
export ANTHROPIC_API_KEY="sk-..."
pupil build
# 4. Chat with the agent interactively
pupil run
# 5. Or run it as an HTTP server
pupil run --port 8080
# 6. Push the image to a registry
pupil push registry.example.com/my-agent:v1pupil create accepts a --template flag. Available templates: minimal (default), full, knowledge-base, chatbot. You can also set the model with --model (defaults to claude-sonnet-4-6).
Pupil's learning process is agentic. During pupil build, an LLM reads your curriculum content, comprehends it, and decides what to store as memories in recalld (an MCP memory server running inside the container). The agent reads the content, understands it, and organizes the knowledge accordingly.
If you define tests in a tests.yaml file, the build includes a self-test cycle. After learning, the agent is tested against your questions. If it fails to meet the minimum pass rate, it re-studies the specific source documents linked to the failed questions (without seeing the test answers). This loop repeats until the agent passes or exhausts its retry budget.
After learning completes, docker commit snapshots the container filesystem (including the recalld database) into an OCI image. The result is a self-contained agent image that you can run anywhere containers run.
pupil create --> pupil teach --> pupil build --> pupil run
| | | |
Scaffolds Adds files/ LLM reads & Starts the
pupil.yaml URLs to the learns the agent in a
+ curriculum/ curriculum/ curriculum, container
directory snapshots image (chat or HTTP)
| Command | Description |
|---|---|
pupil create <name> |
Create a new agent directory with pupil.yaml and curriculum/ |
pupil teach <paths...> |
Add content to an agent's curriculum |
pupil build |
Build an agent: learn the curriculum and snapshot the image |
pupil run |
Run an agent: start the container and begin chatting |
pupil test |
Run tests against a built agent |
pupil push <registry> |
Push an agent image to an OCI registry |
pupil pull <registry> |
Pull an agent image from an OCI registry |
pupil list |
List locally registered agents |
pupil export |
Export an agent as an OCI archive tar file |
pupil import |
Import an agent from an OCI archive tar file |
pupil status |
Show agent status, build info, and runtime usage |
pupil logs |
Show logs from a running agent container |
pupil doctor |
Validate the environment: container runtime, API keys, Ollama |
pupil config |
Get, set, or list global configuration values |
pupil inspect |
Inspect learned memories: list, search, stats, quality, graph, diff |
pupil watch |
Watch curriculum for changes and re-learn automatically |
pupil commit |
Snapshot runtime volume state into a new image |
pupil sync |
Check URL sources for changes and re-learn |
pupil router |
Manage the multi-agent router |
pupil completions |
Generate shell completion scripts |
Pupil uses the genai crate and supports any provider it supports:
- Anthropic (Claude)
- OpenAI (GPT)
- Google (Gemini)
- Ollama (local models)
- AWS Bedrock
- Google Vertex AI
- Azure OpenAI
Set the appropriate API key environment variable for your chosen model (e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY).
The examples/phantomwiki-agent directory contains a complete working agent evaluated against the PhantomWiki benchmark (ICML 2025). PhantomWiki generates fictional wiki articles about made-up characters, then tests whether systems can answer questions about them. Since the characters don't exist, any correct answer must come from learned knowledge, not the model's training data.
cd examples/phantomwiki-agent
./setup.sh # downloads the dataset
pupil build
pupil run
# Run the PhantomWiki benchmark against the built agent
pupil test --file benchmark/phantomwiki.yamlOn the PhantomWiki n=50 benchmark (112 questions, depth 1-4), a Pupil agent using Gemini 2.5 Flash scores 56.2% pass rate. For context, the PhantomWiki paper reports F1 scores of 52.4% for DeepSeek-R1-32B and 50.7% for GPT-4o using Chain-of-Thought, and 30.9% for Gemini 1.5 Flash using ReAct. Note that pass rate and F1 are different metrics, so these numbers are not directly comparable. See Benchmark Results for methodology, caveats, and reproduction steps.
- User Guide -- getting started, full workflow, all commands
- Configuration Reference --
pupil.yaml,tests.yaml, global config, environment variables - Architecture -- two-crate design, container strategy, learning pipeline
- Testing -- writing tests, assertion types, self-test during build
- Benchmark Results -- PhantomWiki evaluation, methodology, reproduction
- Glossary -- terminology and definitions
AGPL-3.0. See LICENSE for details.