What is Protege?
Protege is a mini-framework for building agentic applications — products with an AI agent inside them. It ships as a Rails engine you mount into your own app. The agent isn't a separate service you call out to; it runs in your process, shares your models and jobs, and reaches the outside world the way a colleague would — over email.
The mental model: hiring a colleague
When someone joins a team you do two things. You give them an email address so they can communicate, and you give them access to a workspace so they can do the work. Protege is exactly that split:
- Email is the channel — the agent's mouth and ears. Inbound mail arrives through Action Mailbox; replies go out over SMTP. The agent has a real address and threads conversations like anyone else.
- Your Rails app is the workspace — the agent's hands. It acts on your app through tools you write: plain Ruby classes that call your models, services, and jobs directly.
Everything else in Protege is in service of that model. Rails supplies the plumbing for free: Active Job runs the asynchronous work, Action Mailbox receives the mail, and ActiveRecord persists every thread and message.
The running example: The Scoop
These docs build one example throughout — The Scoop, an ice cream company running its support and order management on Protege. Its Rails app already has Customer, Order, Flavor, and Refund models. Onto that we hire two agents:
- Sundae (
support@thescoop.com) — the customer-facing agent: answers questions, looks up orders, issues refunds, reads a photo a customer attached. - Scout (
ops@thescoop.com) — an internal agent, locked to company senders, that runs scheduled duties like the morning low-stock report.
Each concept below is introduced by giving Sundae or Scout something new. The tutorial grows The Scoop capability by capability; the reference documents every surface.
The LOGI model
Protege organizes an agentic system into four responsibilities — Loop, Orchestrator, Gateway, Inference. Each maps to a concrete part of the engine, and each is independent: you can swap the model without touching your tools, add a tool without touching the inference loop, and add scheduled behavior without touching inbound handling.
| Layer | Responsibility | In the engine |
|---|---|---|
| Loop | Autonomous work on a schedule — the agent initiates | Protege::Loop — responsibilities + cron dispatch |
| Orchestrator | The inference cycle — assemble context, call the model, run tools, persist | Protege::Orchestrator::Harness |
| Gateway | The protocol edge — email in and out, routing, guards | Protege::Gateway + Protege::AgentMailbox |
| Inference | The model, behind a normalized request/response | Protege::Provider adapters |
The Architecture section covers each layer in depth. For the original conceptual framing, see The era of agentic application frameworks.
The request lifecycle
When a customer emails Sundae, here is the path from inbound message to reply:
Inbound email (customer → support@thescoop.com)
│ Action Mailbox
▼
Protege::AgentMailbox ──► persona lookup · access check · recursion guard · bounce-if-unrouted
│ Gateway.accept_smtp_message
▼
Protege::InferenceJob (enqueued via Active Job)
│
▼
Orchestrator::Harness
├─ resolver chain ──► assembles context (system prompt, customer record, thread history)
├─ provider tool loop ──► model ⇄ tools (LookupOrder, ProcessRefund, …), bounded by max_tool_turns
└─ persists every message (Protege::Message / EmailThread) and tool call (ToolUse)
│
▼
send_email tool ──► outbound SMTP ──► the reply lands back in the customer's threadThe same tool loop serves both inbound email and Scout's scheduled work, through two harness subclasses — ReplyHarness (shown above) and ResponsibilityHarness. A scheduled run carries no inbound message; its responsibility_resolvers chain assembles the whole turn instead.
The extension surfaces
You build an agent by writing four kinds of plain-Ruby extension in app/. The engine discovers and wires them for you.
| Surface | Base class | What it does | Discovery |
|---|---|---|---|
| Tools | Protege::Tool | Actions the model can take in your app | Auto (subclasses) |
| Providers | Protege::Provider | LLM backend adapters | By provider_id |
| Resolvers | Protege::Resolver | Assemble the context sent to the model | Added to a persona chain |
| Hooks | Protege::Hook | React to lifecycle events | Auto (subclasses) |
Alongside them, personas (Protege::Persona subclasses) are the agent identities behind each email address, and responsibilities are their scheduled duties. Everything is ordinary Rails, so you test it the way you test the rest of your app.
Where to go next
- Build it: the tutorial starts from
rails newand ends with Sundae and Scout in production. - Look something up: the Extensions and Reference sections document every surface.
- Understand the internals: the Architecture section walks each LOGI layer.

