Skip to content

Talon + Postgram: persistent agent memory in one command

Every conversation with a stateless agent starts at zero. You explain your project, your preferences, your constraints — and the next time you message it, you’re back at square one. The new Talon + Postgram starter stack fixes this with persistent memory that survives across conversations, daemon restarts, and even full container rebuilds.

The starter stack is a Docker Compose setup with three published images: Postgres with pgvector, Postgram, and Talon. Download a tarball, fill in four secrets, run ./bootstrap.sh, and you have an agent that remembers.

Postgram provides four memory primitives the agent uses reflexively:

PrimitiveWhat it does
CaptureStore decisions, constraints, and preferences as they emerge
DistilSearch the knowledge store silently before answering
SurfaceRecall specific stored items by ID when referenced
BroadcastCreate tasks for follow-ups that cannot be done now

The agent does not ask permission to use memory. The postgram-memory skill is marked eager: true, so its guidance — search before answering, store concisely, task what you cannot do now — is always in the system prompt. Memory work is reflexive, not a feature to toggle.

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ postgres │────▶│ postgram │◀────│ talond │
│ (pgvector) │ │ (REST+MCP) │ │ (agent) │
└─────────────┘ └─────────────┘ └─────────────┘

Postgres holds the data. Postgram serves a REST API and an MCP/SSE endpoint on port 3100. Talon connects to Postgram over the compose network via the postgram-memory skill, which carries an MCP client definition rendered with a minted API key.

No host ports are exposed by default. Postgram is internal; Talon reaches it at http://postgram:3100. If you want to poke Postgram from the host or run the UI separately, you can uncomment a loopback-only port mapping.

You might expect docker compose up -d to be enough. It is not — Postgram API keys must be minted after its server is running. The key does not exist until pgm-admin key create runs inside the healthy container.

bootstrap.sh handles the ordering:

  1. Brings up Postgres and Postgram, polls health until Postgram is ready.
  2. Mints a Postgram API key with read, write, and delete scopes.
  3. Writes the key to .env and renders it into the skill’s MCP definition.
  4. Brings up Talon.

The script is safe to re-run. If PGM_API_KEY is already set, it skips key creation and proceeds to step 4.

skills/postgram-memory/SKILL.md is the guidance layer. It tells the agent when to search (before answering when the user references prior context), when to store (decisions, root causes, constraints, preferences), and when to task (follow-ups that cannot be done now). Because the skill is eager, this guidance is always present — the agent does not need to “decide” to load memory.

The MCP client definition lives in skills/postgram-memory/mcp/postgram.json, rendered from a template by bootstrap.sh with the minted API key. Without this rendering step, the agent would have a placeholder key and no connection to Postgram.

The stack ships with sensible defaults. You copy two files and edit four secrets:

Terminal window
cp .env.example .env # POSTGRES_PASSWORD, OPENAI_API_KEY, ANTHROPIC_API_KEY, TELEGRAM_BOT_TOKEN
cp config/talond.example.yaml config/talond.yaml # set allowedChatIds

config/talond.yaml wires the assistant persona to the postgram-memory skill and binds it to a Telegram channel. To use a different provider — Gemini CLI, Codex CLI, or an OpenAI-compatible endpoint — change the provider and model fields. See the Providers guide for details.

The starter stack is the foundation. From here you can add more personas with different skills and providers, bind additional channels (Slack, Discord, email), or extend Postgram with custom entity types and graph relationships.

For the full setup walkthrough — including common operations, troubleshooting, and security notes — see the new Talon + Postgram Starter Stack guide.