personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 198 lines 7.5 kB view raw view rendered
1# Prompt Template System 2 3This document describes solstone's template variable system for personalizing prompts used in generators and agents. Templates enable dynamic substitution of owner identity, contextual information, and reusable prompt fragments. 4 5## Overview 6 7Prompts are stored as `.md` files with optional JSON frontmatter for metadata. The prompt content is loaded via `load_prompt()` from `think/prompts.py`, which uses Python's `string.Template` with `safe_substitute`. This means: 8 9- Variables use `$name` or `${name}` syntax 10- Undefined variables are left as-is (no errors) 11- Use `$$` to escape a literal dollar sign 12 13The system supports three categories of variables with the following precedence (highest to lowest): 14 151. **Context variables** - Passed by callers at runtime 162. **Identity variables** - From journal configuration 173. **Template variables** - From reusable template files 18 19## File Format 20 21Prompt files use JSON frontmatter with `{` and `}` as delimiters (braces on their own lines): 22 23```markdown 24{ 25 "title": "Activity Synthesis", 26 "color": "#00bcd4", 27 "schedule": "segment" 28} 29 30$segment_preamble 31 32# Segment Activity Synthesis 33 34Your prompt content here... 35``` 36 37Files without metadata can omit the frontmatter entirely - just write the prompt content directly. 38 39## Variable Categories 40 41### Identity Variables 42 43Identity variables come from the `identity` block in `config/journal.json`. These are available in all prompts automatically. 44 45**Common variables:** 46- `$name` - Full name 47- `$preferred` - Preferred name or nickname 48- `$bio` - Self-description 49- `$timezone` - IANA timezone identifier 50 51**Pronoun variables** (flattened from nested structure): 52- `$pronouns_subject` - e.g., "he", "she", "they" 53- `$pronouns_object` - e.g., "him", "her", "them" 54- `$pronouns_possessive` - e.g., "his", "her", "their" 55- `$pronouns_reflexive` - e.g., "himself", "herself", "themselves" 56 57**Uppercase-first versions** are automatically generated for all identity variables: 58- `$Name`, `$Preferred`, `$Bio` 59- `$Pronouns_subject`, `$Pronouns_possessive`, etc. 60 61The flattening logic converts nested objects using underscore separators. For example, `identity.pronouns.subject` becomes `$pronouns_subject`. 62 63**References:** 64- Identity configuration: [config.md](../talent/journal/references/config.md) (identity section) 65- Flattening implementation: `think/prompts.py``_flatten_identity_to_template_vars()` 66 67### Template Variables 68 69Template variables come from `.md` files in the `think/templates/` directory. Each file's stem becomes a variable name containing its contents. 70 71**Current templates:** 72- `$daily_preamble` - Preamble for full-day output analysis 73- `$segment_preamble` - Preamble for single-segment analysis 74- `$activity_preamble` - Preamble for activity-level analysis (uses `$activity_*` context variables) 75 76Templates can themselves use identity and context variables, enabling composable prompt construction. For example, `daily_preamble.md` uses `$preferred` and `$day`. 77 78**Pattern:** To add a new template variable, create `think/templates/mytemplate.md` and it becomes available as `$mytemplate` in all prompts. 79 80**Reference:** `think/templates/` directory 81 82### Context Variables 83 84Context variables are passed at runtime by the code calling `load_prompt()`. These are use-case specific and not globally available. 85 86**Common generator context:** 87- `$day` - Human-readable date (e.g., "Friday, January 24, 2026") 88- `$day_YYYYMMDD` - Day in YYYYMMDD format (e.g., "20260124") 89- `$facet` - Focused facet name when the prompt is dispatched per-facet (bare name, e.g. `work`) 90- `$activity_md_dir` - Directory path containing per-activity narrative `.md` outputs for the focused facet/day, with trailing slash 91- `$now` - Current date and time with timezone (e.g., "Monday, February 3, 2025 at 10:30 AM PST") 92- `$segment` - Segment key (e.g., "143022_300") 93- `$segment_start` - Formatted start time (e.g., "2:30 PM") 94- `$segment_end` - Formatted end time (e.g., "2:35 PM") 95 96**Activity context** (available for `schedule: "activity"` agents): 97- `$activity_id` - Activity record ID (e.g., "coding_095809_303") 98- `$activity_type` - Activity type (e.g., "coding", "meeting") 99- `$activity_description` - Description of the activity 100- `$activity_level` - Average engagement level (0-1) 101- `$activity_entities` - Comma-separated active entities 102- `$activity_segments` - Comma-separated segment keys 103- `$activity_duration` - Estimated duration in minutes 104 105Context variables also get automatic uppercase-first versions (`$Day`, `$Day_yyyymmdd`, etc.). 106 107**References:** 108- Generator context building: `think/generate.py` (search for `prompt_context`) 109- Other callers: `observe/extract.py`, `observe/enrich.py` 110 111## Usage Patterns 112 113### For Generators 114 115Generator prompts typically compose a shared preamble with agent-specific instructions: 116 117```markdown 118{ 119 "title": "My Generator", 120 "color": "#4caf50", 121 "schedule": "segment" 122} 123 124$segment_preamble 125 126# Segment Activity Synthesis 127 128Your specific instructions here... 129``` 130 131The `$segment_preamble` or `$daily_preamble` template provides standardized context about what's being analyzed, while the rest of the prompt defines the specific analysis task. 132 133**Optional model configuration:** Add `max_output_tokens` (response length limit) and `thinking_budget` (model thinking token budget) to override provider defaults. 134 135**Reference:** `talent/*.md` for examples (files with `schedule` field but no `tools` field) 136 137### For Agents 138 139Agent prompts are `.md` files with configuration in frontmatter: 140 141```markdown 142{ 143 "title": "My Agent", 144 "tier": 2, 145 "tools": "journal" 146} 147 148You are a helpful assistant... 149``` 150 151**Optional model configuration:** Add `max_output_tokens` (response length limit) and `thinking_budget` (model thinking token budget) to override provider defaults. Note: OpenAI uses fixed reasoning and ignores `thinking_budget`. 152 153**Reference:** `think/talent.py``get_talent()` for agent configuration loading 154 155### The load_prompt() Function 156 157```python 158load_prompt( 159 name: str, # Prompt filename (without .md) 160 base_dir: Path | None = None, # Directory containing prompt 161 context: dict | None = None, # Runtime context variables 162) -> PromptContent 163``` 164 165Returns a `PromptContent` named tuple with `text` (substituted content), `path` (source file), and `metadata` (frontmatter dict). 166 167**Reference:** `think/prompts.py``load_prompt()` 168 169## Adding New Variables 170 171### Identity Variables 172 173Edit `config/journal.json` to add or modify identity fields. Nested objects are automatically flattened with underscore separators. 174 175### Template Variables 176 177Create a new `.md` file in `think/templates/`. The filename stem becomes the variable name. 178 179### Context Variables 180 181Pass via the `context` parameter when calling `load_prompt()`: 182 183```python 184load_prompt("myprompt", context={"custom_var": "value"}) 185``` 186 187## Reference Index 188 189| Category | Authoritative Source | 190|----------|---------------------| 191| Identity config schema | [config.md](../talent/journal/references/config.md) (identity section) | 192| Identity flattening | `think/prompts.py` (`_flatten_identity_to_template_vars`) | 193| Template loading | `think/prompts.py` (`_load_templates`) | 194| Core load function | `think/prompts.py` (`load_prompt`) | 195| Template files | `think/templates/*.md` | 196| Test coverage | `tests/test_template_substitution.py` | 197| Generator prompts | `talent/*.md` (files with `schedule` field but no `tools`) | 198| Agent prompts | `talent/*.md` (files with `tools` field) |