# Agent Tasks: Short-Term Memory via Context-Injected Task List ## Summary Add a **tasks** system that serves as the agent's short-term working memory. The agent can break down goals into steps, track progress, and see its current task list in every prompt context. Tasks are file-backed (not stored on Nostr) and managed via a dedicated `task_manage` tool. ## How It Works ```mermaid flowchart TD A[User sends message] --> B[Context builder runs] B --> C[Template resolver hits tasks_content variable] C --> D[Read tasks.json from disk] D --> E{Tasks exist?} E -->|Yes| F[Format tasks as readable text] E -->|No| G[Return empty string - section skipped] F --> H[Inject as system message in prompt] G --> H H --> I[LLM sees current tasks in context] I --> J{LLM decides to update tasks?} J -->|Yes| K[LLM calls task_manage tool] K --> L[Tool updates tasks.json on disk] L --> M[Tool result returned to LLM] J -->|No| N[LLM responds normally] ``` ## Design ### Storage: `tasks.json` A simple JSON file in the agent's working directory. Structure: ```json { "tasks": [ { "id": 1, "text": "Query admin relay list to find active relays", "status": "done", "created_at": 1709535600, "updated_at": 1709535660 }, { "id": 2, "text": "Draft long-form article about Nostr relay setup", "status": "active", "created_at": 1709535600, "updated_at": 1709535600 }, { "id": 3, "text": "Publish article as kind 30023", "status": "pending", "created_at": 1709535600, "updated_at": 1709535600 } ], "next_id": 4 } ``` Task statuses: `pending`, `active`, `done` ### Tool: `task_manage` A single tool with an `action` parameter that covers all operations: | Action | Parameters | Description | |--------|-----------|-------------| | `list` | *(none)* | Return all tasks with status | | `add` | `text`, optional `status` | Add a new task, default status `pending` | | `update` | `id`, optional `text`, optional `status` | Update text and/or status of a task | | `remove` | `id` | Remove a task by ID | | `clear` | optional `status` | Remove all tasks, or all with a given status | | `replace` | `tasks` (array of text strings) | Replace entire task list with new items | The `replace` action is important — it lets the LLM rewrite the whole plan in one call rather than doing add/remove/update one at a time. This is the most common pattern: the agent works out a plan and writes all steps at once. **Tool schema:** ```json { "name": "task_manage", "description": "Manage the agent task list - short-term working memory for tracking steps in a plan. Tasks appear in your context on every message.", "parameters": { "type": "object", "properties": { "action": { "type": "string", "enum": ["list", "add", "update", "remove", "clear", "replace"] }, "text": { "type": "string" }, "id": { "type": "integer" }, "status": { "type": "string", "enum": ["pending", "active", "done"] }, "tasks": { "type": "array", "items": { "type": "string" } } }, "required": ["action"] } } ``` ### Context Section: `agent_tasks` New section in the context template, placed after `adopted_skills` and before `dm_history`: ```yaml - section: agent_tasks role: system skip_if_empty: true content: | {{tasks_content}} ``` ### Template Variable: `{{tasks_content}}` New resolver in `agent_template_resolve_var()` that: 1. Reads `tasks.json` from the working directory 2. Parses the JSON 3. Formats active/pending tasks as readable text 4. Returns empty string if no tasks exist (section gets skipped via `skip_if_empty`) **Rendered format in context:** ``` ### Current Tasks Your active task list - short-term working memory for tracking plan steps. - [x] 1. Query admin relay list to find active relays - [-] 2. Draft long-form article about Nostr relay setup - [ ] 3. Publish article as kind 30023 ``` Legend: `[x]` = done, `[-]` = active, `[ ]` = pending Done tasks are included so the agent has continuity about what it already accomplished, but they could be pruned after a configurable count or age to save tokens. ### System Prompt Addition Add to the agent's behavioral rules in the soul/system prompt: ``` ### Task Management - You have a task list that serves as your short-term working memory. - When working on multi-step goals, use task_manage to track your plan. - Update task status as you complete steps. - Your current tasks appear in your context automatically. ``` ## Implementation Steps ### 1. Add `task_manage` tool implementation in `tools.c` - New `execute_task_manage()` function - Reads/writes `tasks.json` in the working directory (uses `build_tool_path` for sandboxing) - Handles all 6 actions: list, add, update, remove, clear, replace - Returns JSON result with success/failure and current task list ### 2. Register `task_manage` tool schema in `tools_build_openai_schema_json()` - Add tool definition (t35 or next available) with the schema above ### 3. Wire `task_manage` into `tools_execute()` dispatch - Add `strcmp(tool_name, "task_manage")` branch calling `execute_task_manage()` ### 4. Add `{{tasks_content}}` template variable resolver in `agent.c` - New `build_tasks_content_string()` function - Reads `tasks.json`, formats as markdown checklist - Add to `agent_template_resolve_var()` for var name `tasks_content` ### 5. Add `agent_tasks` section to context template - Add the new section in `context_template.md` - Place after `adopted_skills`, before `dm_history` - Use `skip_if_empty: true` so it costs zero tokens when no tasks exist ### 6. Add section detection for context logging - Add `agent_tasks` detection in `detect_context_section()` in `agent.c` ### 7. Add task management guidance to system prompt - Brief behavioral instruction so the agent knows when/how to use the task list ## Token Budget Considerations - Empty task list: **0 tokens** (skipped via `skip_if_empty`) - Typical 5-task plan: **~80-120 tokens** - Maximum reasonable list of 15 tasks: **~250-350 tokens** - Consider pruning done tasks older than N turns or keeping only the last M done tasks ## Future: User-Facing To-Do List (Nostr) This is explicitly **not** the user-facing to-do list. That future feature would: - Store items as Nostr events (likely a NIP-51 style list or custom kind) - Be visible to the user via Nostr clients - Have its own separate tool (`todo_manage` or similar) - Potentially reference agent tasks that graduate to user-visible items The agent tasks system is purely internal working memory. ## Files Modified | File | Change | |------|--------| | `src/tools.c` | Add `execute_task_manage()`, tool schema, dispatch entry | | `src/agent.c` | Add `build_tasks_content_string()`, resolver entry, section detection | | `context_template.md` | Add `agent_tasks` section | | Soul/system prompt (kind 31120) | Add task management behavioral guidance |