Prompt Assembly
Not one giant string. Every system prompt is assembled in discrete layers — each with a clear source, defined scope, and explicit separation of concerns.
Layer architecture
Lower layers are always present. Upper layers are selected at runtime by the OpenAI text runtime.
Always present in every prompt
Recent conversation history, current user message, and any active crisis signals injected from runtime state.
The exact instruction for this runtime task — what to write, what format to use, what constraints apply. Includes response_guidance for turn-specific shaping.
A therapeutic lens selected by the TherapeuticAgent as therapeutic_approach: MI, CBT, ACT, DBT skills, grief support, IPT, or PFA.
The response style selected by the runtime and specialist agent. Shapes the goal and tone of the turn — supportive, reflective, clarifying, psychoeducation, technique, guided_exercise, closing, safety_check, or crisis_response.
The permanent foundation: who OpenCouch is, what it will and won't do, and the hard safety and privacy boundaries that no response style can override.
How the layers combine
| Layer | Question it answers | Source | Per turn? |
|---|---|---|---|
| Core | Who is this system? What are the hard rules? | core_identity.md, policy/boundaries.md, policy/privacy.md (collected as CORE_SOURCES in prompts/__init__.py) | Never changes |
| Response style | What response shape is this turn? | response_styles/*.md — support, reflection, psychoeducation, guided_exercise, closing, crisis_response, safety_check | Selected by agent-owned skill/tool context |
| Therapeutic approach | What therapeutic framework overlay? | Seven selectable approaches under therapeutic_approaches/ — motivational_interviewing, cbt (loads cbt.md + cbt_arc.md), act, dbt_skills, grief_support, interpersonal_therapy, pfa | Per turn, selected by runtime state and skill context |
| Instructions | How should it respond on this turn specifically? | agent/specialists/therapeutic_response/prompt_instructions.py, agent/specialists/guided_exercise.py, and agent/guardrails/prompts.py | Per response style |
| Working memory | What does it know about the user? | Semantic + episodic entries from the load-memory stage | Re-retrieved each turn |
| Procedural rules | What style rules apply? | Rules from ProceduralProfile, injected as suffix | Loaded each turn |
Working memory shapes the agent's awareness — "Previously noted: user has a sister named Sarah." Procedural rules shape its behavior — "this user prefers shorter responses." Rules are always applied regardless of the proactive recall toggle.
The crisis branch composes a tighter prompt: CORE_SOURCES +
response_styles/crisis_response.md (and policy/crisis.md for the
classifier prompt) + recent history. Memory layers are skipped on
crisis turns by design.
The safety_check response style is used when the crisis
classifier returns level 1 (ambiguous distress, needs_clarification)
— a one-question safety probe inside the therapeutic branch rather
than a full crisis response.
Why layers
| Property | How layers enforce it |
|---|---|
| Safety policy can't be overwritten | Core layer (including policy/boundaries.md + policy/privacy.md) is always first; no style/approach can weaken it |
| Response knowledge is reviewable | Each response style's knowledge is a standalone .md in agent/prompts/sources/response_styles/ |
| Procedural rules can't be overridden | Injected last as system prompt suffix; safety-conflict rules ("skip the safety check") are dropped by the procedural extractor |
| Each layer has a clear owner | agent/prompts/sources/ for content, agent/specialists/ for agent-owned assembly, and agent/guardrails/ for crisis prompt assembly |
Implementation
| File | What it does |
|---|---|
agent/prompts/__init__.py | CORE_SOURCES tuple, load_prompt_source(), compose_sources(), format_recent_history(), plus crisis prompt builder re-exports |
agent/guardrails/prompts.py | Crisis classifier + crisis response prompt builders |
agent/specialists/therapeutic_response/prompt_sources.py | _knowledge_for_response_style() and response-style / approach source selection |
agent/specialists/therapeutic_response/prompt_instructions.py | Per-response-style instruction blocks |
agent/specialists/therapeutic_response/prompts.py | Therapeutic-agent system/task prompt builders |
agent/specialists/guided_exercise.py | Guided-exercise specialist instructions and system prompt builder |
agent/prompts/sources/core_identity.md | Assistant role, product stance, voice, tone, pacing, directness, and core boundaries |
agent/prompts/sources/policy/ | Safety + privacy + crisis policy (3 files) |
agent/prompts/sources/response_styles/ | One file per response style (7 files) |
agent/prompts/sources/therapeutic_approaches/ | 8 knowledge files across 7 selectable approaches (CBT loads both cbt.md and cbt_arc.md), dynamically loaded per turn |
agent/prompts/sources/session_stages.md | Stage-aware response guidance (not yet wired into the runtime) |
agent/prompts/sources/cross_session_continuity.md | First-turn catch-up framing |
agent/runtime/memory_context.py | Populates working_memory and procedural_profile.procedural_rules |
Compatibility matrix
Which response styles pair with which therapeutic approaches, and which combinations the dispatcher can actually pick.
| Response | What it does | MI | CBT | ACT | DBT | Grief | IPT | PFA |
|---|---|---|---|---|---|---|---|---|
| supportive | Default support lane — validate, reflect, and respond based on venting, strengths, or gentle guidance. | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| reflective | Explore a named recurring pattern carefully without over-analyzing. | ✓ | ✓ | ✓ | — | ✓ | ✓ | — |
| clarifying | Ask for the minimum context needed before choosing a deeper response. | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| psychoeducation | Explain one likely mind-body process in simple, non-diagnostic language. | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| technique | Structured therapeutic work without launching a named multi-turn exercise. | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| guided_exercise | State-tracked practice such as grounding, breathing, thought work, values, or emotion regulation. | — | ✓ | ✓ | ✓ | — | — | ✓ |
| closing | Wind down, reflect the useful part, and avoid opening a large new thread. | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| safety_check | Ambiguous risk signal — ask one direct safety clarification. | — | — | — | — | — | — | ✓ |
| crisis_response | Confirmed risk — prioritize immediate safety and surface resources. | — | — | — | — | — | — | ✓ |
This is the intended routing surface, not a hard static registry. The therapeutic response agent selects a response skill throughload_therapeutic_response_skill; prompt source loading lives in agent/specialists/therapeutic_prompt_sources.py. Hover a column to highlight it.
Live assembly
Real (trimmed) excerpts generated from backend prompt dumps. Pick a scenario, hit play, and watch which layers light up as the animation walks past each section header. The "skipped" rows show which layers a given scenario deliberately omits (e.g., the crisis path drops the procedural-rules and recall-toggle blocks by design).
The default therapeutic turn — soul + identity + boundaries + privacy + supportive response style + MI overlay + recall hint.
Layers light up as the typing animation walks past each section header in the prompt.