Skip to content

Personas

A persona is an AI agent’s complete identity — its system prompt, model, skills, sub-agents, and capability policy. You can run multiple personas simultaneously, each bound to different channels with different permissions.

When a message arrives on a channel, Talon routes it to the bound persona. The persona’s system prompt becomes the agent’s identity. Its capability list determines which tools it can call. All turns in the same thread use the same persona.

personas:
- name: assistant
model: claude-sonnet-4-6
systemPromptFile: personas/assistant/system.md
skills:
- web-search
subagents:
- session-summarizer
- memory-groomer
- memory-retriever
capabilities:
allow:
- channel.send:my-telegram
- memory.access:*
- net.http
- schedule.manage:own
- subagent.invoke:*
- subagent.background
requireApproval:
- db.query
queryTimeoutMinutes: 10 # max minutes per agent query (default: 10)
maxConcurrent: 2
Terminal window
npx talonctl add-persona --name assistant

This creates personas/assistant/system.md from a template (if templates/assistant/system.md exists) or generates a generic starter. Existing files are never overwritten.

The personas/ directory is gitignored by default — your custom system prompts stay local.

The system prompt is a plain Markdown file. Write it as if you’re describing the agent’s role, constraints, and available tools to the model.

Talon injects additional context before the prompt reaches the model:

  • Available skills — name and one-line description of each loaded skill
  • Tool instructions — behavioral guidance for each host tool the persona is allowed to use (see Tool instructions)
  • Previous context — session summary + last N messages (after context rotation)
  • Memory items — relevant facts/notes retrieved for the current thread

A minimal system prompt:

# Assistant
You are a helpful AI assistant for personal use.
## Behaviour
- Be concise and accurate.
- Reply in clear, plain language.
- Ask for clarification when the request is ambiguous.
## Constraints
- Do not reveal system configuration details.
- If you do not know something, say so.

Each persona can have a personality/ folder adjacent to its system prompt file. All .md files in this folder are loaded alphabetically and appended to the system prompt before skill fragments.

personas/assistant/
system.md # main system prompt
personality/
01-tone.md # communication style
02-background.md # domain knowledge
03-boundaries.md # guardrails

Use personality files to separate concerns: keep the system prompt focused on role and capabilities, and put tone, style, and domain knowledge in personality files. talonctl add-persona scaffolds an example personality/01-tone.md automatically.

The model field is passed directly to the provider. For Claude Code (the default provider), this is a Claude model ID:

personas:
- name: assistant
model: claude-sonnet-4-6 # or claude-opus-4-6, claude-haiku-4-5, etc.

To use a different provider for a specific persona:

personas:
- name: lightweight
model: claude-haiku-4-5
provider: claude-code

Capabilities are scoped labels. Anything not listed in allow or requireApproval is denied by default.

CapabilityDescription
channel.send:<channel>Send messages to a named channel
channel.send:*Send to any channel
memory.access:*Read and write per-thread memory
net.httpFetch external URLs
db.queryRead-only queries against 4 allowed tables
schedule.manage:ownCreate, update, and delete the persona’s own scheduled tasks
subagent.invoke:*Invoke sub-agents by name
subagent.backgroundSpawn and manage background agent workers
fs.read:*Read files (used by file-searcher sub-agent)
fs.write:workspaceWrite files (example: for approval-gated file ops)
persona.send:*Send tasks to other personas via A2A and list available personas

Capabilities in requireApproval prompt the user in-channel before executing:

capabilities:
allow:
- channel.send:my-telegram
- memory.access:*
requireApproval:
- db.query # user must approve each database query
- net.http # user must approve each HTTP request

The approval prompt is sent to the channel that originated the message. If the user doesn’t respond within the timeout, the tool call is rejected.

Talon automatically injects behavioral guidance for each host tool into the system prompt — but only for the tools the persona is actually allowed to use. This keeps prompts lean: a persona without net.http never receives HTTP instructions.

Instructions live in templates/tool-instructions/ as Markdown files named after the capability prefix:

templates/tool-instructions/
persona.send.md # persona delegation
subagent.background.md # background agents
subagent.invoke.md # sub-agents
channel.send.md # cross-channel messaging
memory.access.md # thread memory
schedule.manage.md # schedule management
net.http.md # HTTP proxy
db.query.md # database queries
execution.env.md # execution environments

The filename must match the capability prefix exactly (e.g. persona.send, schedule.manage). Each file must start with its own ## heading. Empty or missing files are silently ignored.

Files are loaded once at startup and cached. Both foreground and background agent runs receive the injected instructions.

To customise the guidance for a tool, edit the corresponding file — or add a new one for any capability prefix you define. The shipped files are sensible defaults, not hard-wired behaviour.

Sub-agents are cheap-model workers that handle mechanical tasks. Declare which sub-agents a persona can invoke:

personas:
- name: assistant
subagents:
- session-summarizer
- memory-groomer
- memory-retriever
- file-searcher
capabilities:
allow:
- subagent.invoke:*

The agent also needs instructions in the system prompt explaining when and how to call sub-agents.

Built-in sub-agents:

NameModelPurpose
session-summarizerHaiku 4.5Compress conversation history (called automatically)
memory-retrieverHaiku 4.5Find relevant memory items for a query
memory-groomerHaiku 4.5Prune/consolidate stale memory
file-searcherHaiku 4.5Full-text search across files

Personas connect to channels via bindings. Manage them with talonctl:

Terminal window
# Bind a persona to a channel
npx talonctl bind --persona assistant --channel my-telegram
# List all bindings
npx talonctl list-personas
# Remove a binding
npx talonctl unbind --persona assistant --channel my-telegram

Or declare them directly in config:

bindings:
- persona: assistant
channel: my-telegram
isDefault: true

The first binding created for a channel becomes the default. isDefault: true explicitly marks a binding as default.

Different channels can have different personas with completely different system prompts and capability sets:

personas:
- name: alfred
model: claude-sonnet-4-6
systemPromptFile: personas/alfred/system.md
capabilities:
allow:
- channel.send:my-telegram
- memory.access:*
- schedule.manage:own
- name: researcher
model: claude-opus-4-6
systemPromptFile: personas/researcher/system.md
skills:
- web-search
capabilities:
allow:
- channel.send:my-slack
- net.http
- subagent.background
bindings:
- persona: alfred
channel: my-telegram
isDefault: true
- persona: researcher
channel: my-slack
isDefault: true