Skip to content

Talon + Postgram Starter Stack

The Talon + Postgram starter stack is a self-contained Docker Compose setup that wires Talon to a persistent knowledge store so your agent remembers across conversations. Nothing to build — three published images, one command, and you have a running agent with memory.

Without memory, every conversation starts blank. The starter stack fixes that by running Postgram alongside Talon on the same Docker network. Postgram stores facts, decisions, preferences, and tasks in a Postgres database with vector embeddings for semantic search. Talon’s agent queries Postgram silently before answering and stores what matters without being asked.

The bundled postgram-memory skill gives the agent four primitives:

PrimitiveToolWhen to use
Capturepostgram_storeA decision is made, a constraint discovered, or a preference stated
Distilpostgram_searchThe user references something from a previous conversation
Surfacepostgram_recallRetrieve a specific stored item by ID
Broadcastpostgram_task_createA follow-up is identified that cannot be done now

Three containers on one compose network:

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ postgres │────▶│ postgram │◀────│ talond │
│ (pgvector) │ │ (REST+MCP) │ │ (agent) │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │
│ │
http://postgram:3100 MCP over SSE
ServiceImageRole
postgrespgvector/pgvector:pg17Postgram’s database with the pgvector extension
postgramghcr.io/ivo-toby/postgramKnowledge store — REST API and MCP/SSE endpoint on port 3100
talondghcr.io/ivo-toby/talondThe Talon agent daemon, wired to Postgram via the postgram-memory skill

Postgram is internal to the compose network — Talon reaches it at http://postgram:3100. No host port is exposed by default.

Terminal window
# 1. Download and extract the stack
curl -fsSL https://github.com/ivo-toby/talon/releases/latest/download/talon-postgram-stack.tar.gz | tar xz
cd talon-postgram-stack
# 2. Configure secrets
cp .env.example .env
# Edit .env: POSTGRES_PASSWORD, OPENAI_API_KEY, ANTHROPIC_API_KEY, TELEGRAM_BOT_TOKEN
cp config/talond.example.yaml config/talond.yaml
# Edit config/talond.yaml: set allowedChatIds for Telegram
# 3. Bring up the stack
./bootstrap.sh
# 4. Message your Telegram bot

That’s it. The bootstrap script handles the ordering, mints a Postgram API key, renders the skill’s MCP definition, and starts the daemon.

If you have Claude Code installed, you can configure the stack interactively instead of editing files by hand. After extracting and cding into the directory:

Terminal window
claude

Then use any of these skills inside Claude Code:

SkillCommandWhat it does
Setup/talon-setup-dockerTop-level guided setup — walks through .env, config/talond.yaml, and the bootstrap script
Add Telegram/add-telegramConfigures Telegram bot token and allowed chat IDs
Add Slack/add-slackSets up Slack app credentials and channel bindings
Add Discord/add-discordConfigures Discord bot token and guild settings
Add WhatsApp/add-whatsappSets up WhatsApp Business API credentials
Add Email/add-emailConfigures SMTP/IMAP email channel
Add Terminal/add-terminalEnables the local terminal channel
Create profile/create-profileCreates a new persona with a system prompt
Create personality/create-personalityCustomizes a persona’s voice and tone
Manage schedules/manage-schedulesSets up scheduled agent runs

The skills are Docker-aware and understand the starter-stack layout. For first-time setup they guide you through editing .env and config/talond.yaml manually; for follow-on changes they drive talonctl directly.

Why bootstrap.sh instead of docker compose up

Section titled “Why bootstrap.sh instead of docker compose up”

Postgram API keys must be minted after its server is running. You cannot pre-set one in .env because the key does not exist until Postgram’s admin CLI creates it. bootstrap.sh handles this ordering:

  1. Starts postgres and postgram, waits until Postgram reports healthy.
  2. Mints a Postgram API key via pgm-admin key create inside the running container.
  3. Writes the key into .env as PGM_API_KEY and renders it into skills/postgram-memory/mcp/postgram.json.
  4. Starts talond.

The script is idempotent — if PGM_API_KEY is already set, it skips key creation and reuses the existing key.

The skill lives in skills/postgram-memory/ and has two parts:

MCP client (mcp/postgram.json, rendered from .template by bootstrap.sh):

{
"name": "postgram",
"config": {
"transport": "sse",
"url": "http://postgram:3100/mcp",
"headers": {
"Authorization": "Bearer <your-minted-key>"
}
}
}

Usage guidance (SKILL.md), marked eager: true:

The eager: true flag means the skill’s guidance is always included in the agent’s system prompt. Memory use is reflexive — the agent should not have to decide to “load” it. The guidance tells the agent to search silently before answering, store concisely when decisions are made, and create tasks for follow-ups that cannot be done now.

The assistant persona in config/talond.yaml lists postgram-memory in its skills: array, so every agent run gets both the tools and the guidance.

File or directoryPurpose
.envSecrets. bootstrap.sh fills in PGM_API_KEY automatically. Never commit this file.
config/talond.yamlTalon configuration — channels, persona, provider, bindings. Copied from talond.example.yaml.
personas/<name>/system.mdPersona system prompts. The starter includes an assistant persona.
.claude/skills/Claude Code setup skills — guided, interactive configuration for channels, personas, and schedules.
skills/postgram-memory/The skill that wires Talon to Postgram. Contains SKILL.md and the MCP definition.
userdata/Files for the agent to read, bind-mounted at /userdata inside the container.
data/Talon’s SQLite database, PID file, and IPC sockets. Persists across restarts.
VariableSet inPurpose
POSTGRES_PASSWORD.envPostgres password, used only inside the compose network
OPENAI_API_KEY.envPostgram uses this to embed knowledge for semantic search
TELEGRAM_BOT_TOKEN.envFrom @BotFather
ANTHROPIC_API_KEY.envClaude Code provider API key (or see Providers for alternatives)
PGM_API_KEY.envFilled automatically by bootstrap.sh. Leave blank initially.

The starter defaults to Claude Code (claude-sonnet-4-6). To use a different provider — Gemini CLI, Codex CLI, or an OpenAI-compatible endpoint — edit config/talond.yaml and set the provider and model fields on the persona. See the Providers guide for configuration examples.

Terminal window
# Check service status
docker compose ps
# Follow Talon logs
docker compose logs -f talond
# Follow Postgram logs
docker compose logs -f postgram
# Check daemon health from the host
talonctl status
# Stop the stack (data persists in volumes)
docker compose down
# Update images and restart
docker compose pull && ./bootstrap.sh

The talonctl helper is installed by ./install.sh to ~/.local/bin by default. It wraps the container’s CLI so you can run commands from the host without docker compose exec.

bootstrap.sh says Postgram didn’t become healthy

Section titled “bootstrap.sh says Postgram didn’t become healthy”

Check Postgram’s logs:

Terminal window
docker compose logs postgram

Most common cause: OPENAI_API_KEY is missing or invalid. Postgram needs it to generate embeddings. Verify the key is set in .env and has quota available.

Confirm the MCP file was rendered correctly:

Terminal window
cat skills/postgram-memory/mcp/postgram.json

It should contain a real API key, not __PGM_API_KEY__. If the placeholder is still there, re-run ./bootstrap.sh.

Check Talon’s logs for MCP connection errors:

Terminal window
docker compose logs talond | grep -i mcp
  • Verify TELEGRAM_BOT_TOKEN is correct and the bot is started in @BotFather.
  • Ensure allowedChatIds in config/talond.yaml contains your Telegram user ID as a string (e.g., "123456789", not 123456789). Find your ID via @userinfobot.
  • Check docker compose logs talond for channel-specific errors.

For more Telegram troubleshooting, see the Channels guide.

  • .env contains secrets. It is listed in .gitignore by default. Never commit it.
  • Postgram is not exposed to the host by default. To access it from the host (for example, to run the Postgram UI separately), uncomment the ports: block in docker-compose.yaml and bind to 127.0.0.1:3100 only.
  • Talon runs as a non-root user (1000:1000) with all Linux capabilities dropped and no-new-privileges:true.
  • Read the Memory guide to understand Talon’s four-layer memory architecture.
  • Explore the Postgram documentation for the knowledge store API and query syntax.
  • Add more personas or channels in config/talond.yaml — the stack supports multiple personas with different skills and providers.