docs · start

Concepts#

Hekma treats each AI agent you run as a service: it starts and stops the agent's process, watches it, counts the tokens it spends, and acts when a budget is crossed. This page defines the handful of words the rest of the docs use. Read the first diagram and the bold terms to get the whole model in two minutes; each section links to the page that goes deeper.

Diagram source (Mermaid)
flowchart TD
    You["You: hekma CLI<br/>or your own program"] --> Engine["Hekma engine"]
    Engine --> Adapter["Adapter<br/>(built-in kind or adapter.toml)"]
    Engine --> State[("State directory:<br/>fleet, usage ledger, Agent Homes")]
    Adapter --> Agent["Agent process<br/>(OpenCode, Hermes, your script)"]
    Agent -->|model calls| Provider["Model provider"]
    Agent -.->|usage| Engine

You register an agent once. Hekma stores its settings and gives it a private folder. From then on, any hekma command, or a program that embeds Hekma's engine, can start it, stop it, read its usage and enforce its budget. The engine does that work only while some process holds it open, which is the most important limit to understand in Hekma 0.11.0 (see supervision).

Agents and adapters#

Agent#

An agent is a program you already run that calls a language model on your behalf: a coding agent such as OpenCode, a personal agent such as Hermes Agent, or a script of your own. Hekma does not help you write agents. It runs them as operating-system processes and governs them from the outside.

Each registered agent has a unique name (lowercase letters, digits, - and _, starting with a letter or digit). The docs and the CLI also call a registered agent an Agent Instance; it is the same thing. You can register the same program several times under different names, each with its own settings, budget and history.

Adapter#

An adapter tells Hekma how to run one kind of agent: the command that launches it, what it supports on each operating system, and where its token counts come from. There are two sorts:

AdapterHow you registerUse it for
Built-in kind--kind acp, --kind hermes, --kind mockAgents Hekma knows natively. acp runs any Agent Client Protocol agent.
Manifest--manifest /path/to/my-agentAny other program. You describe it in an adapter.toml.

Adapters follow a versioned adapter contract, currently 1.0.0. A manifest names the contract version it was written for, and Hekma refuses a manifest whose major version it does not support.

Capability declaration#

Not every agent can do everything on every operating system. Pausing a process, for example, is reliable on macOS and Linux and only cooperative on Windows. Each adapter carries a capability declaration that rates every capability per OS as guaranteed, best-effort or unsupported. Hekma acts on it: a guaranteed pause suspends the process, a best-effort pause prints a note, and an unsupported one fails before anything happens. hekma agent show NAME prints the declaration for your OS.

Agent Home#

Every agent gets its own folder, its Agent Home, inside the state directory. It holds the agent's settings, logs, rendered config files and, if you attach one, its memory folder. The agent's process starts with the Agent Home as its working directory. The Agent Home separates agents' files from each other; it is not a security sandbox, so an agent can still read anything your user account can.

Fleet#

The fleet is every agent registered in one state directory. hekma agent list shows the fleet as a table, and hekma agent usage without a name adds up the fleet's token totals.

Running agents#

Lifecycle#

Every agent is always in exactly one state, and moves between states only through a fixed set of transitions:

Diagram source (Mermaid)
flowchart TD
    registered -->|start| starting
    starting --> running
    starting --> failed
    running -->|pause| paused
    paused -->|resume| running
    running -->|stop| stopping
    paused -->|stop| stopping
    stopping --> stopped
    running -->|crash| failed
    stopped -->|start| starting
    failed -->|"start, or restart policy"| starting
StateMeaning
registeredKnown to Hekma, never started.
startingThe process is being launched.
runningThe process is up.
pausedThe process is suspended (or asked to idle, on Windows).
stoppingHekma asked the process to exit and is waiting.
stoppedThe process exited after a stop.
failedThe process crashed, failed to launch, or was gone when Hekma looked for it. The reason is recorded.

You drive the arrows marked with commands (start, stop, pause, resume). Hekma drives the others when it sees the process start, exit or crash. A command that does not fit the current state, such as pausing a stopped agent, fails with exit code 4 and changes nothing.

Run#

A run is one life of an agent's process, from a start until it stops or crashes. Per-run budgets and "this run" usage numbers reset when a new run begins. A restart after a crash starts a new run; a detached agent stays in one run across all the commands that look at it.

In development: a Run is becoming the unit every Hekma verb acts on, first for supervised agents and the work a Host opens inside them (workloads Hekma does not launch follow, planned), and a Restart Policy relaunch will continue the same Run instead of starting a new one. See Runs, Control Depth, ps and top.

Restart policy#

When a supervised process exits on its own, Hekma records a crash and applies the agent's restart policy. The default, on-failure, starts it again after 1 second, then after 2, 4 and 8 seconds, and gives up at the fifth crash in a row, leaving the agent failed. The count goes back to 0 only when you start the agent yourself. The other policy, never, leaves a crashed agent failed. The policy can be changed through the embedding API; the CLI shows it in hekma agent show.

Engine#

The engine is the part of Hekma that does the work: it keeps the fleet's records, launches and watches processes, meters usage and enforces budgets. It is a Rust library, hekma-engine. The hekma command opens the engine for the length of one command; your own program can embed it and keep it open as long as it likes.

Supervision#

Supervision is the engine watching an agent: noticing crashes and restarting it, counting its tokens as they are reported, and acting on budget breaches. It happens only while a process holds the engine open.

In Hekma 0.11.0 that means:

  • Each hekma command supervises for as long as it runs. Most commands finish in a fraction of a second; hekma agent logs NAME --follow keeps running until you stop it, so it keeps supervision going.
  • A program that embeds the engine supervises for as long as it keeps the engine open.
  • Between commands, nothing supervises a detached agent: no crash detection, no budget enforcement, and usage the agent reports in that time is not counted later.

hekma agent list and show have a Supervision column that reads detached, session, or — when no process is recorded. A long-running host that supervises all the time, hekma serve, is on Hekma's main branch (Unreleased: after 0.11.0). Supervision and detached runs explains the patterns that work today.

Detached#

By default, an agent started by hekma agent start belongs to that command and stops when the command exits. hekma agent start NAME --detach leaves it running after the command exits. The next hekma command finds it again by its process id and start time, which Hekma calls adoption, and supervises it for as long as that command runs. A detached agent's stdin is closed, so you cannot send it input from the CLI.

Usage and money#

Metering source#

Every adapter declares where its token counts come from, its metering source:

SourceHow it worksTrust
self-reportedThe agent, or a small wrapper, prints one KTESIO_USAGE {...} line per model call.You trust the agent to report.
engine-observedThe agent sends its model traffic through a proxy the engine runs on 127.0.0.1, and the engine reads the token counts from the provider's responses.The counts come off the wire, so the agent cannot under-report.

Meter token usage shows how to set up each one.

Usage ledger#

The usage ledger is Hekma's durable record of every usage event: input, output and cached tokens, per agent and per run, with replays removed. Every token number Hekma shows, and every budget decision it makes, comes from the ledger.

Budget#

A budget is a ceiling on an agent's tokens or estimated dollars, either per run or cumulative over the agent's life. Budgets are ordinary config values such as budget.tokens.cumulative. Hekma checks them in the same step that writes new usage to the ledger, so the breach is acted on at the usage event that crossed the line. Budgets and cost covers them in full.

Breach action#

The breach action decides what happens when any budget is crossed: pause (the default in 0.11.0) suspends the agent, stop stops it, and warn only records the breach. A breach is acted on once per run.

In development: warn, with loud signals, becomes the default, and pause and stop become opt-in; agents that relied on the old default keep pause. See Policies and the warn default.

Rate#

A rate is a price per million tokens, set separately for input, output and cached tokens (cost.rate.input and so on). With rates set, Hekma derives an estimated dollar cost for every usage event and can enforce dollar budgets. Without a rate, dollar budgets do nothing. Costs are kept as whole micro-dollars and always shown as estimates, because only your provider's invoice is authoritative.

Settings and state#

Config layers#

Each agent's settings are key-value pairs such as model or budget.breach_action. They resolve from layers: the adapter kind's defaults, then the engine level, then the agent's own instance layer, where hekma agent config set writes. The most specific layer wins, and hekma agent config get shows each value with the layer it came from. Keys Hekma does not know must start with agent., and are passed to the agent through its adapter's config mapping. See Config keys.

Secrets#

A config value of the form secret:NAME is a secret reference. Hekma stores only the reference. When the agent starts, it resolves NAME from the environment, then from secrets.toml in the state directory, and hands the real value to the agent, while every Hekma output (tables, JSON, logs, events) keeps it masked. hekma agent config get NAME --reveal is the only way to see it. See Config, secrets and memory.

Memory backing#

A memory backing gives an agent durable memory that Hekma looks after. A filesystem backing is a memory/ folder inside the Agent Home that Hekma creates, keeps across restarts and never touches, and passes to the agent at each start. A native backing records that the agent manages its own memory. You attach or detach one while the agent is stopped.

State directory#

Everything Hekma knows lives in one state directory: a SQLite database (state.db) with the fleet and the usage ledger, an optional secrets.toml, and one Agent Home per agent under agents/.

OSDefault location
macOS~/Library/Application Support/ktesio
Linux~/.local/share/ktesio (or $XDG_DATA_HOME/ktesio)
Windows%APPDATA%\ktesio\data

The folder keeps the name ktesio from before the product was renamed, so existing installs keep their data. Set HEKMA_STATE_DIR to an absolute path to use another folder, for example one per project or a throwaway one for experiments.

Diagram source (Mermaid)
flowchart TD
    Root["state directory"] --> DB[("state.db<br/>fleet + usage ledger")]
    Root --> Secrets["secrets.toml<br/>(optional, owner-only)"]
    Root --> Agents["agents/"]
    Agents --> Home["NAME/ (the Agent Home)"]
    Home --> Conf["config.toml<br/>effective-config.json"]
    Home --> Logs["logs/<br/>output.log, agent.log,<br/>instance.log, breaches.log"]
    Home --> Mem["memory/<br/>(if a filesystem backing is attached)"]