Skip to content

Main concepts

A plugin extends the Cat through a handful of primitives, each a small Python class or decorated function the Cat discovers at startup. Everything comes from a single front door:

from cat import Agent, tool, Directive, hook, endpoint, store, user, log

This page is the map. Each primitive links to its full reference in the Plugins section.

An agent is a loop: it reads the conversation, optionally calls tools, and answers. The other primitives sit around that loop, some steer it, some watch it, some expose it to the outside world.

flowchart LR
    C(["Client message"]) --> EP["Endpoints<br/>HTTP surface"]
    EP --> A

    subgraph A ["Agent (the loop)"]
        direction TB
        D["Directives<br/>steer the loop"] --> L{{"LLM turn"}}
        L --> T["Tools<br/>the agent's hands"]
        T --> L
    end

    A --> R(["Reply"])
    H["Hooks<br/>react to lifecycle events"] -.watch.-> A
    A -.read / write.-> P["store / user<br/>persistence"]

An agent is a loop. Tools are its hands. Directives hook the loop. Hooks react to the lifecycle. Endpoints open the door.

Primitive What it is Reach for it when
Agent A loop with a system_prompt, some tools and some directives. Subclass Agent, give it a slug, clients talk to it. You want something to talk to.
Tool A method decorated with @tool the LLM can decide to call. Its docstring and type hints are the manual the LLM reads. The agent needs to do something: query a DB, hit an API.
Directive Reusable middleware over the loop (start / step / finish). RAG, memory and guardrails are all just directives. You need to touch the agent itself, per turn.
Hook A data-only reaction to a global lifecycle event (message in, message out, app boot). Never sees the agent. You react to the pipeline and don’t need the agent.
Custom Endpoint Extend the REST API with @endpoint.get/post/..., guarded by a single role= kwarg. You want your own HTTP routes.
Persistence Two key-value stores from the front door: store (shared) and user (per person). You need to remember state between requests.
Settings A pydantic schema the Cat renders as a form in the admin UI. An admin should configure your plugin.
Dependencies A requirements.txt the Cat installs with the plugin. Your plugin needs extra Python packages.
Logging from cat import log — level-aware, colorized console logging. You want to trace what your plugin does.

The one distinction people trip on: both extend behaviour, but only one gets the agent.

  • Need to touch the agent (its prompt, its tools, its result)? Write a Directive, agent-scoped, opt-in.
  • Just reacting to a pipeline event, no agent involved? Write a Hook, data-only.

Start with an Agent and give it a Tool, that is a complete, useful plugin. From there, add Directives, Hooks, Endpoints and Persistence as you need them.