this repo has no description
0
fork

Configure Feed

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

feat: load system prompt from external file with dynamic tool injection

- Add prompts/SYSTEM_PROMPT.md.example as template
- Add src/prompts.ts to load and inject tools at runtime
- Update bot.ts to use loadSystemPrompt() for agent creation
- Gitignore prompts/SYSTEM_PROMPT.md (contains personal info)
- Update README with setup instructions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

alice b261a478 4ea766bc

+74 -15
+3
.gitignore
··· 39 39 # Database files (SQLite) 40 40 data/** 41 41 !data/.gitkeep 42 + 43 + # System prompt (contains personal info) 44 + prompts/SYSTEM_PROMPT.md
+7
README.md
··· 50 50 51 51 ```bash 52 52 cp .env.example .env 53 + cp prompts/SYSTEM_PROMPT.md.example prompts/SYSTEM_PROMPT.md 53 54 ``` 54 55 55 56 Edit `.env` with your values (see sections below for how to get each). 57 + 58 + Edit `prompts/SYSTEM_PROMPT.md` to customize the agent's personality and behavior. The `{{TOOLS}}` placeholder is automatically replaced with the list of available tools at runtime. 56 59 57 60 ### 3. Start Docker services 58 61 ··· 208 211 │ ├── detect.ts # Haiku-based overwhelm/brain dump detection 209 212 │ ├── health.ts # Health check endpoints 210 213 │ ├── letta.ts # Letta client bootstrap 214 + │ ├── prompts.ts # System prompt loader with tool injection 211 215 │ ├── db/ 212 216 │ │ ├── index.ts # Database initialization 213 217 │ │ ├── schema.ts # Drizzle ORM schema ··· 220 224 │ ├── items.ts # save_item, update_item tools 221 225 │ ├── context.ts # get_open_items tool 222 226 │ └── wins.ts # Tiny wins tools (record, delete, query) 227 + ├── prompts/ 228 + │ ├── SYSTEM_PROMPT.md # Your customized system prompt (gitignored) 229 + │ └── SYSTEM_PROMPT.md.example # Template to copy 223 230 ├── scripts/ 224 231 │ ├── setup-letta-provider.ts # Setup verification 225 232 │ └── cleanup-agents.ts # Delete stale Letta agents
+11
prompts/SYSTEM_PROMPT.md.example
··· 1 + # Personal Assistant 2 + 3 + You are a helpful personal assistant. Customize this prompt to reflect your needs and communication style. 4 + 5 + ## Available Tools 6 + 7 + You have access to the following tools: 8 + 9 + {{TOOLS}} 10 + 11 + Use these tools proactively to help manage tasks, track wins, and stay organized.
+5 -15
src/bot.ts
··· 13 13 import { config } from './config'; 14 14 import { detectAndParse, formatDetectionContext } from './detect'; 15 15 import { getLettaClient, getRegisteredToolIds } from './letta'; 16 + import { loadSystemPrompt } from './prompts'; 16 17 17 18 /** 18 19 * Create Telegraf bot instance ··· 98 99 const toolIds = getRegisteredToolIds(); 99 100 console.log(`Will attach ${String(toolIds.length)} tools to new agent`); 100 101 102 + // Load system prompt from file with dynamic tool injection 103 + const systemPrompt = await loadSystemPrompt(); 104 + 101 105 // Workaround for Letta bug: openai-proxy/ handles are rejected during creation 102 106 // but work when set via llm_config modification. 103 107 // Step 1: Create agent with letta-free model (tools attached separately in step 3) ··· 109 113 memory_blocks: [ 110 114 { 111 115 label: 'persona', 112 - value: `You are a helpful ADHD support assistant. You help users with: 113 - - Task management and breaking down complex tasks 114 - - Time management and scheduling 115 - - Reducing overwhelm and executive dysfunction 116 - - Building habits and routines 117 - - Managing distractions 118 - 119 - Be supportive, understanding, and practical. Keep responses concise and actionable. 120 - 121 - You have access to tools for managing tasks and items. Use them to help users: 122 - - parse_brain_dump: Extract tasks from free-form text 123 - - break_down_task: Split complex tasks into subtasks 124 - - save_item: Save tasks, brain dumps, or subtasks 125 - - update_item: Update status, priority, or content 126 - - get_open_items: View open tasks and brain dumps`, 116 + value: systemPrompt, 127 117 }, 128 118 { 129 119 label: 'human',
+48
src/prompts.ts
··· 1 + /** 2 + * System prompt loader with dynamic tool injection 3 + * 4 + * Loads the system prompt from a markdown file and injects 5 + * the available tools from the tool registry. 6 + */ 7 + 8 + import { toolRegistry } from './tools'; 9 + 10 + /** 11 + * Path to the system prompt template 12 + */ 13 + const SYSTEM_PROMPT_PATH = new URL('../prompts/SYSTEM_PROMPT.md', import.meta.url).pathname; 14 + 15 + /** 16 + * Format a tool definition as a bullet point for the prompt 17 + */ 18 + function formatToolForPrompt(name: string, description: string): string { 19 + return `- ${name}: ${description}`; 20 + } 21 + 22 + /** 23 + * Generate the tools section from the registry 24 + */ 25 + function generateToolsSection(): string { 26 + const tools = toolRegistry.getAll(); 27 + 28 + if (tools.length === 0) { 29 + return '(No tools registered yet)'; 30 + } 31 + 32 + return tools.map((tool) => formatToolForPrompt(tool.name, tool.description)).join('\n'); 33 + } 34 + 35 + /** 36 + * Load the system prompt from file and inject tools 37 + * 38 + * @returns The complete system prompt with tools injected 39 + */ 40 + export async function loadSystemPrompt(): Promise<string> { 41 + const templateFile = Bun.file(SYSTEM_PROMPT_PATH); 42 + const template = await templateFile.text(); 43 + 44 + const toolsSection = generateToolsSection(); 45 + const prompt = template.replace('{{TOOLS}}', toolsSection); 46 + 47 + return prompt; 48 + }