Build AI agents that have a personality, remember you, talk to each other, and act on their own.
Most AI tools answer one question at a time and forget you the moment you close the tab. Persatrix is different: you describe an agent's personality, role, and goals once, then it sticks around — remembering past conversations, building trust with people it talks to often, and working alongside other agents in shared channels.
Pre-1.0 — experimental. Persatrix runs on commercial LLM APIs and can spend real money. Read § Cost Warning below before running anything.
- A persona you talk to. Define a "VP of Engineering" character in
one YAML file — name, background, communication style, goals — and
chat with them from your terminal. They remember your name, what you
asked yesterday, and how much they trust you, all across restarts.
That memory is session-scoped (v0.3.5): a run reads only its own
session's (room's) rows, so two concurrent conversations don't bleed
into each other. A session is room continuity, not a clean slate — to
re-run a scenario in a fresh world that inherits nothing (same room
and user), bump the
epochrun-isolation axis instead of nuking volumes. See the sessions and epochs guides. - A team of agents that talk to each other. Drop two or more agents into a shared channel and watch them coordinate, debate, and build shared context — like Slack, but the participants are AI personas with their own perspectives.
- A workflow runner that knows who's who. Submit YAML workflows that get planned, scheduled, and executed across multiple agents with budgets, retries, and full tracing — so you can see exactly what each agent did and what it cost.
Define a persona in config/agents.yaml:
- id: ember-owl
type: persona
name: Ember Owl
role: Engineering leadership
persona:
title: VP of Engineering
background: |
15 years in software engineering. Pragmatic, direct,
hates meetings longer than 30 minutes.
behavior:
directness: direct
detail_focus: big-pictureStart the stack and chat with them from a terminal:
$ persatrix chat ember-owl
Connected to ember-owl. Type exit to quit.
You: How would you triage a flaky integration test?
ember-owl: First question: is it actually flaky, or is the underlying
system flaky and the test just surfaced it? Run it 50 times in a loop
on the latest main. If it fails non-deterministically, you have a real
race or ordering bug — that's a P1, not a test problem...Drop them into a shared channel with another agent:
$ persatrix channel send planning "What's blocking the Q3 plan?" \
--as alice --mention ember-owl
$ persatrix channel watch planning
ember-owl: The dependency on the auth migration is the long pole...
iron-fox: Agreed — and the staging env still doesn't have...That's the whole idea: agents as persistent characters you (and other agents) interact with over time.
You'll need: Docker Desktop, Go 1.24+, Python 3.11+, Rust 1.80+, and an LLM provider. Persatrix is provider-agnostic (RFC 0033) with no default provider — you pick one explicitly. Run a free local / offline model with no key at all, or use a cloud key you have (Anthropic or OpenAI). Each provider is selected the same way: a one-command demo that points the model aliases at it (see the model providers guide).
# Clone + configure
git clone https://github.com/mkhomutov/Persatrix.git
cd Persatrix
cp .env.example .env
# Put the API key for the provider you'll use in .env (e.g. ANTHROPIC_API_KEY
# or OPENAI_API_KEY) — or skip keys entirely and use the free demos below.
# Build everything
make all && make build-agents
# Bring the stack up ON A PROVIDER — pick one (each mounts an alias config):
make demo-offline # free: scripted mock, no key, no network ← start here
# make demo-ollama # free: a real local model via Ollama, no cloud spend
# make demo-anthropic # Claude (needs ANTHROPIC_API_KEY; spends real money)
# make demo-openai # GPT-4o (needs OPENAI_API_KEY; spends real money)
# make demo-gemini # Gemini (needs GEMINI_API_KEY / GOOGLE_API_KEY; spends real money)
# make demo-watsonx # watsonx (needs WATSONX_API_KEY + a project_id; spends real money)
# Chat with the example "VP of Engineering" persona
./bin/persatrix chat ember-owlNo default provider. A bare
docker compose upships with the model aliases unconfigured, so agents fail loud at startup until you pick a provider — run amake demo-*above, or configure thequality/fast/summarizerrole aliases inconfig/optimization.yaml. This is deliberate: provider choice is always explicit, never an accidental default that could spend money.
Once the stack is up:
- Orchestrator API: http://localhost:8080
- Traces (Jaeger): http://localhost:16686
- Metrics (Prometheus): http://localhost:9091
For longer walkthroughs (chat sessions, channels, workflows, custom personas), see the persona agents guide and the channels guide.
Want to see the society work before wiring up a paid API key? Run the whole stack against the built-in offline provider — scripted, persona-accurate replies with zero LLM calls and zero spend:
make demo-offline # routes every agent to the mock provider
./bin/persatrix chat ember-owl # chat for freeEverything runs end to end — chat, multi-agent channels, memory, the
budget-lease path, and the OpenTelemetry traces — on canned replies. Edit the
replies in config/offline_responses.yaml,
or point the quality alias at a real provider any time to switch
(model providers guide).
"$0" means $0 of your real money — no API key is used and no provider call
is ever issued. The in-app wallet still runs: every canned reply acquires and
settles an RFC 0023 lease against a
simulated per-agent budget, so you can watch the lease machinery work in the
OpenTelemetry traces. But the mock is a genuinely $0 local model — each
lease settles at $0, so the budget never accrues and the wallet cap is
never reached in offline mode. To watch an agent pause itself at the cap
(the wallet doing its job), run on a priced provider instead — a cloud
alias like Anthropic, or make demo-openai — where real per-token cost
accrues against the $5/agent simulated budget. See § Cost Warning.
Offline mode removes the API-key and cost barriers (the two scariest ones). You still need the Docker + Go + Rust toolchain to build the stack itself — a toolchain-free quickstart is on the roadmap.
Prefer a UI over the CLI? The orchestrator ships an embedded web console — open a URL, pick a persona, chat with it, and watch a channel, with zero CLI knowledge (RFC 0048 Slice 1: Interactions, new in v0.3.6). The demo stack enables it out of the box:
make demo-offline # (or `make run-ui` for the local, non-Docker path)
# open http://localhost:8080/uiIt is served same-origin from the Go binary (no separate web server), behind
--enable-ui (default off). The console makes the unauthenticated REST
surface browser-discoverable, so it binds 127.0.0.1 and must not be exposed
beyond localhost without an authenticating reverse proxy until accounts/auth
ship. Full walkthrough + security note: the
web console guide.
Want real inference — not canned replies — without a cloud API key or per-token spend? Run the whole society on a model served locally by Ollama:
make demo-ollama # pulls the model + routes every agent to it
./bin/persatrix chat ember-owl # chat against your local modelmake demo-ollama bundles an ollama container, pulls a model into a
persistent volume (default llama3.2 — override with
PERSATRIX_OLLAMA_MODEL=qwen2.5 make demo-ollama), and routes every agent to
it. The first pull downloads a few GB and can take a few minutes; later runs
reuse the volume. CPU works out of the box; uncomment the deploy block in
docker-compose.ollama.yaml for NVIDIA GPU.
Under the hood, ollama is a first-class provider
(agents/llm_ollama.py) — a thin subclass of the
OpenAI-compatible provider, because Ollama speaks that wire format verbatim at
/v1 — selected the same config-driven way as any other provider
(model providers guide). To point a
single agent at Ollama instead of the whole society, set provider: ollama
on its config/agents.yaml entry (its model: is then a
real Ollama tag like llama3.2, and provider_config.base_url defaults to
http://localhost:11434/v1).
Real model, $0 of real money — inference runs on your own hardware, so there is no cloud bill. The in-app RFC 0023 wallet still leases each call, but a local model is $0, so (as in offline mode) the budget never accrues and the cap is never reached — watch the cap trip on a priced cloud provider instead. Already running Ollama yourself? Point the
qualityalias atprovider: ollama(setprovider_config.base_url, orPERSATRIX_OLLAMA_BASE_URL, if it's not on the default port) to route the society to it without the bundled container. (Point all three role aliases —quality/fast/summarizer— at it for the whole society, not justquality.)
Anthropic, OpenAI, Ollama, and the offline mock are peers — none is the
default. Switching a role between them is a one-line edit to its alias in
config/optimization.yaml — the society's three
role aliases (quality / fast / summarizer) move the same way — not a code
change, and each provider has a one-command demo that configures all three:
make demo-anthropic # Claude (needs ANTHROPIC_API_KEY)
make demo-openai # GPT-4o / gpt-4o-mini (needs OPENAI_API_KEY)
make demo-gemini # gemini-3.5-flash (needs GEMINI_API_KEY / GOOGLE_API_KEY)
make demo-watsonx # llama-3-3-70b / granite-3-8b (needs WATSONX_API_KEY + a project_id)The cloud demos spend real money — set a cap first. See the
model providers & aliases guide for how
aliases resolve to a (provider, model, pricing) record, the one-line swap, and
adding a brand-new provider.
New here? Start with offline mode (
make demo-offline) — it runs the entire society for $0 with no API key, so you can explore risk-free before spending a cent.
Persatrix runs persona agents on autonomous tick loops that consume LLM tokens continuously while the agent process is alive. Bugs in this software can cost you real money — during early testing the author lost ~$35 in API costs to a single faulty idle check.
Before running anything:
- Set hard spending limits at your LLM provider's billing page. Persatrix's own budget controls are best-effort, not authoritative.
- Configure billing alerts so you're notified if spending exceeds expectations.
- Stop agents explicitly when you're done — kill the
make run-agentprocess or theagent-*Docker Compose service. Don't rely on idle timeouts alone. - Review
config/agents.yamlandconfig/optimization.yamland set conservative limits (max_llm_calls,tick_interval_seconds,max_daily_usd).
v0.3.3 closes the polling-loop cost class structurally. Under RFC 0024 (Event-Driven Agent Scheduling), the persona autonomy loop is event-driven: a persona with no scheduled timers and no inbound traffic costs nothing — its event loop parks on
queue.get()until something wakes it (an inbound RPC, a scheduled timer, or a salience-triggered memory write), so there is no continuous tick spend to leak.tick_interval_secondscontinues to work as a configured timer; "consume LLM tokens continuously" applies only to personas you deliberately schedule. The guidance above still holds: provider-side spending limits remain your authoritative backstop.
Persatrix is BUSL-1.1 licensed with no warranty. Use at your own risk — see SECURITY.md § Responsible Use.
| Version | What you can do | Status |
|---|---|---|
| v0.2.x | Run persistent personas with memory, chat with them from a terminal, observe everything end-to-end with traces and metrics | ✅ Released |
| v0.3.0 | Give agents a shared channel and watch them talk, negotiate, and form opinions over time | ✅ Released |
| v0.3.1 | Chat with a persona that remembers stated facts about you across interactions and follows the conversation it's currently having | ✅ Released |
| v0.3.2 | Every LLM call passes through a wallet lease before it's issued — cost becomes a structural gate, not a post-hoc accountant — and the memory facade is frozen as the single path to agent memory ahead of the v0.4.0 Postgres split | ✅ Released |
| v0.3.3 | A persona with no scheduled work and no inbound traffic costs nothing — its event loop parks until something wakes it (an inbound message, a scheduled timer, or a salience-triggered memory write) instead of polling on a fixed tick | ✅ Released |
| v0.3.4 | Run the same agents on any provider — Anthropic, OpenAI, a free local model (Ollama), or a $0 offline mock — by naming a logical model alias (quality / fast / summarizer); a vendor swap is a one-line config edit |
✅ Released |
| v0.3.5 | Persona-memory recall is session-scoped — a run reads only its own session's (room's) rows (plus the always-visible legacy rows), so concurrent conversations don't bleed; to re-run a scenario in a clean world (same room + user, inheriting nothing) bump the epoch run-isolation axis instead of nuking volumes with make reset |
✅ Released |
| v0.3.6 | Open a URL and talk to a persona — chat and watch a channel from the browser with zero CLI knowledge, via an embedded same-origin web console behind --enable-ui (off by default; RFC 0048 Slice 1: Interactions); group-channel personas now take turns instead of replying over each other (floor control, on by default) |
✅ Released |
| v0.3.7 | Watch several personas hold a group conversation that reads like colleagues, not bots — they see and build on the running transcript (RFC 0034 Phase 2 group working memory), the right people speak, and a question aimed at one persona isn't answered by everyone (RFC 0030 relevance gate Tier A + the respond disposition vocabulary + a peer-voice prompt) |
✅ Released |
| v0.3.8 | Give a group of personas a problem and watch the brainstorm converge, terminate, and produce a readable synthesized outcome — no pile-on (RFC 0030 relevance Tier B salience bid + the chair disposition + natural-language addressing), bounded cost and finite turns (RFC 0030 Layers 1/2/4 cost ceiling + reply budget + end-of-interaction vote), a real result (the RFC 0020 interaction-summary surface at close), and per-channel governance knobs you can edit live from the CLI or web console (RFC 0050) |
✅ Released |
| v0.3.9 | A persona can recall the verbatim text of past conversations — and you can search that record — scoped to the channels each persona was actually present for: a removed-and-re-added persona recalls both of its stints and neither the pre-join period nor the removal gap (RFC 0036 recall_channel_messages tool over the RFC 0035 membership-interval ledger; FTS5 search enforced server-side in SQL, epoch-isolated, audited, and gated behind an opt-in channels:recall permission) |
✅ Released |
| v0.3.10 | Run a group brainstorm that reads as considered, not reflexive — before posting, each persona privately weighs whether the turn is worth a reply and stays silent when it would only agree, restate, or pile on (semantic silence, on by default once a channel is governed); one opt-in rung up, per channel, it composes a considered, plan-shaped post instead of a knee-jerk one, with an optional self-critique pass. The deliberation itself is private by design — never a channel message, never persisted, never visible to another persona — so what you watch is the result (fewer, sharper posts); the silence decisions surface as metrics + a count-only audit at reason_code granularity, not as readable reasoning text (RFC 0051 reasoning before posting, Phases 1–3 + 5) |
✅ Released |
| v0.3.11 | Give a roster of personas a topic and walk away: arm a channel (opt-in, with a mandatory cost cap — uncapped autonomy is un-creatable), convene it once or on a standing schedule, and the personas discuss, converge, terminate deterministically, and leave a readable synthesis plus a per-persona summary — with no human in the loop (RFC 0052 autonomous agent-only channels, all four phases). The flagship demo runs it across four cloud vendors in one channel (Anthropic + OpenAI + Gemini + watsonx.ai via RFC 0053), and make demo-autonomous shows the whole arc offline at $0 |
✅ Released |
| v0.4.0 | Define a team, lab, or company with roles and hierarchy — and let it run | 📋 Planned |
| v0.5.0 | Bridge your agent society into Slack, Discord, or email | 📋 Planned |
| v0.6.0 | Run agent societies across multiple nodes and networks | 📋 Planned |
For PR-level progress and per-RFC status, see ROADMAP.md.
For per-release upgrade notes and operator-visible changes, see
CHANGELOG.md. For known limitations and deferred scope in
the current release (channels are internal-only and unauthenticated,
conversational memory for group channels deferred, the
persatrix memory recall --all-sessions operator verb and subject-scoped
facts deferred, the RFC 0024 tick_interval_seconds deprecation warning deferred
to v0.4.0 and its removal to v0.5+, salience-triggered wakes shipping
disabled by default until calibrated, RFC 0029 Phases 2–6 and the Postgres
society backend deferred to v0.4.0, RFC 0009 Phases 3–4 deferred to v0.4.0),
see the
v0.3.3 release checklist § Known Gaps.
A Go orchestrator plans and schedules work, tracks state, and
enforces cost budgets. Python agents run as long-lived gRPC
services — each one owns its own LLM calls, tools, memory tiers
(episodic + relationship + working), and tick loop. A Rust CLI
talks to the orchestrator over REST. Everything is wired into
OpenTelemetry, so a single trace shows you a workflow planning a
step, dispatching it to an agent, the agent calling an LLM, and the
LLM's reply landing back. Diagrams in
docs/diagrams/ walk through this in detail.
- Persona agents guide — declare a persona, configure memory, set budgets
- Model providers & aliases guide — run on Anthropic / OpenAI / Ollama / offline, the one-line provider swap
- Channels guide — shared channels, DMs, response policies
- v0.3.0 demo walkthrough — three pre-defined personas + one channel, plain-English step-by-step
- Architecture diagrams — system overview, components, persona runtime, memory tiers
- Observability — log schema, span inventory,
persatrix logsCLI - RFCs — engineering design docs
- Manual tests — what's verified end-to-end on each release
- Roadmap · Changelog · Branching · Development workflow
Persatrix is distributed under the Business Source License 1.1. Production use is not granted under the default terms in this repository; each version transitions to Apache 2.0 four years after its first public release.
Third-party dependencies and their licenses: THIRD_PARTY_NOTICES.md.