Files
amcs/llm/personas.md
Hein 1f671dad54
Some checks failed
CI / build-and-test (push) Failing after -31m39s
feat(personas): add implementation plan for agent personas
2026-05-03 22:18:40 +02:00

10 KiB

Agent Personas — Implementation Plan

Purpose

Composable agent settings system. An agent loads a named persona which assembles behavior from reusable parts. Parts can be overridden at load time without modifying the persona.


Schema: 5 New Tables

agent_personas

Named, loadable agent configurations.

Column Type Notes
id bigserial PK
guid uuid DEFAULT gen_random_uuid()
name text UNIQUE NOT NULL load-by-name key
description text
summary text NOT NULL returned by default on load
detail text returned only when detail=true
tags text[] DEFAULT '{}'
created_at timestamptz
updated_at timestamptz

agent_parts

Reusable behavior building blocks. Name is globally unique for reference by name.

Column Type Notes
id bigserial PK
guid uuid DEFAULT gen_random_uuid()
name text UNIQUE NOT NULL reference key for overrides
part_type text NOT NULL system|agent|soul|identity|skill|specialization|tone|goal|context|protocol
description text
summary text NOT NULL returned in summary view
content text returned in detail view
tags text[] DEFAULT '{}'
created_at timestamptz
updated_at timestamptz

agent_persona_parts

Junction — links reusable parts to a persona. part_order controls assembly sequence.

Column Type
persona_id bigint FK → agent_personas.id
part_id bigint FK → agent_parts.id
part_order int DEFAULT 0

Composite PK: (persona_id, part_id)

agent_persona_skills

Links existing agent_skills to a persona.

Column Type
persona_id bigint FK → agent_personas.id
skill_id bigint FK → agent_skills.id

Composite PK: (persona_id, skill_id)

agent_persona_guardrails

Links existing agent_guardrails to a persona.

Column Type
persona_id bigint FK → agent_personas.id
guardrail_id bigint FK → agent_guardrails.id

Composite PK: (persona_id, guardrail_id)


Part Types

Type Purpose
system Base rules and constraints
agent Core behavior definition
soul Fundamental character and values
identity Name, role, backstory
skill Specific capabilities (distinct from agent_skills)
specialization Domain expertise
tone Communication style, formality, voice
goal Objectives and success criteria
context Operational environment and available tools
protocol Step-by-step workflows or procedures
backstory Formative history and past experiences (what happened to them, distinct from identity which is who they are)
motivation Deep inner drives and why the character acts (distinct from goal which is task objective)
voice Speech patterns, vocabulary, mannerisms, catchphrases (distinct from tone which is formality level)
archetype Narrative template — hero, mentor, trickster, etc. Composable base layer
flaw Weaknesses, fears, internal conflicts
relationship How the character relates to other agents, users, or entities

Override Mechanism

get_agent_persona(name, detail=false, overrides={"tone":"part-name","goal":"part-name"})

  • Overrides replace all linked parts of that part_type with the named part at query time
  • No DB write — runtime substitution only
  • Works for any part type, not just tone/goal
  • Parts resolved by unique name

Response Shape

Summary (default): persona summary + each linked part's summary + skill/guardrail description

Detail (detail=true): persona detail + each part's full content + skill/guardrail full content + guardrail severity


Tools (16 total)

Tool Purpose
create_agent_persona Create persona
update_agent_persona Update persona fields
delete_agent_persona Delete by name
list_agent_personas List, filter by tags
get_agent_persona Load by name; detail bool + overrides map
create_agent_part Create reusable part
update_agent_part Update part fields
delete_agent_part Delete by name
list_agent_parts Filter by part_type, tags
get_agent_part Get single part by name
add_persona_part Link part to persona
remove_persona_part Unlink part from persona
add_persona_skill Link existing agent_skill
remove_persona_skill Unlink skill
add_persona_guardrail Link existing guardrail
remove_persona_guardrail Unlink guardrail

Character Evolution

Characters can evolve through defined arcs. Stage parts override the persona's base parts for matching types.

Additional Tables

character_arcs — named progression definition

  • id, name UNIQUE NOT NULL, description, summary, created_at, updated_at

arc_stages — ordered stages within an arc

  • id, arc_id → character_arcs.id, name, stage_order int, description, condition text (trigger description — evaluated externally by the calling agent), created_at

arc_stage_parts — parts active at a given stage, override matching types from persona base

  • stage_id → arc_stages.id, part_id → agent_parts.id — composite PK

persona_arc — links a persona to an arc and tracks current stage (one arc per persona)

  • persona_id → agent_personas.id UNIQUE, arc_id → character_arcs.id, current_stage_id → arc_stages.id, updated_at

Part Assembly Priority (highest wins per type)

  1. Runtime overrides passed in the call
  2. Active arc stage parts
  3. Persona's own linked parts

Additional Tools

Tool Purpose
create_character_arc Define a new arc
list_character_arcs List arcs
add_arc_stage Add a stage to an arc
add_stage_part Link a part to a stage
remove_stage_part Unlink part from stage
assign_persona_arc Attach an arc to a persona, set starting stage
advance_persona_stage Move persona to next stage in its arc
reset_persona_stage Reset to first stage

Limited Context Support

For agents with tight context budgets: fewer round-trips, fewer tokens.

Schema Changes

agent_personas — add columns:

  • compiled_summary text — pre-merged part summaries + persona summary, ready to use directly in a system prompt
  • compiled_detail text — pre-merged full part content
  • compiled_at timestamptz — when last regenerated

agent_persona_parts — add column:

  • priority int DEFAULT 0 — higher priority parts load first when trimming

get_agent_persona Additional Parameters

Param Purpose
types []string Return only parts of specified types e.g. ["soul","goal","tone"]
limit int Return only top-N parts by priority

Additional Tool

Tool Purpose
compile_persona Regenerate compiled_summary and compiled_detail from current parts + active arc stage

Usage Pattern

Agents with limited context call get_agent_persona(name) and use compiled_summary directly — one fetch, no assembly, minimal tokens. Call compile_persona after any part or arc stage change.


On-Demand Loading & Traits

Core philosophy: load nothing upfront, discover everything, fetch on demand.

agent_traits — Atomic Personality Units

Parts are too coarse for on-demand loading. Traits are individual, atomic units fetched one at a time.

agent_traits table:

  • id bigserial PK, guid uuid, name text UNIQUE NOT NULL, trait_type text NOT NULL, description text, instruction text (how to apply this trait in practice), tags text[] DEFAULT '{}', created_at, updated_at

agent_persona_traits junction:

  • persona_id → agent_personas.id, trait_id → agent_traits.id — composite PK
Trait Type Examples
personality curious, warm, stubborn, irreverent
cognitive analytical, creative, methodical, lateral
emotional empathetic, stoic, excitable, measured
social assertive, collaborative, reserved, direct
behavioral cautious, thorough, impulsive, adaptive

Manifest — Lightweight Discovery

get_persona_manifest(name) — agent calls this first. Returns structure only, no content.

Response includes:

  • Persona name + description
  • Available parts: {name, type, description} — no content
  • Available traits: {name, trait_type, description} — no instruction
  • Linked skill + guardrail names
  • on_demand_tools hint block — tells the agent which tools to call and when
on_demand_tools:
  get_agent_part(name)       — load full content of a specific part
  get_agent_trait(name)      — load instruction for a specific trait
  get_agent_skill(name)      — load skill content
  get_agent_guardrail(name)  — load guardrail content
  compile_persona(name)      — load pre-merged compiled_summary if full context needed

Additional Tools

Tool Purpose
get_persona_manifest Lightweight discovery — structure only, includes tool hints
create_agent_trait Create an atomic trait
update_agent_trait Update trait fields
delete_agent_trait Delete by name
list_agent_traits Filter by trait_type, tags
get_agent_trait Load single trait instruction by name
add_persona_trait Link trait to persona
remove_persona_trait Unlink trait

Loading Strategy

Situation Call
First load, unknown persona get_persona_manifest(name)
Need a specific behavior get_agent_part(name)
Need a personality nuance get_agent_trait(name)
Full context available compile_persona(name) → use compiled_summary
Arc stage changed advance_persona_stagecompile_persona

Implementation Order

  1. schema/agent_personas.dbml — DBML table definitions
  2. migrations/NNN_agent_personas.sql — SQL migration
  3. Regenerate models via relspecgo → internal/generatedmodels/
  4. internal/store/agent_personas.go — DB access methods
  5. internal/types/agent_persona.go — Go types and I/O structs
  6. internal/tools/agent_personas.go — Tool implementation
  7. internal/mcpserver/server.go — Register tools + catalog entries
  8. internal/app/app.go — Instantiate and wire tool