# `Nous.Tools.TodoTools`
[🔗](https://github.com/nyo16/nous/blob/v0.17.1/lib/nous/tools/todo_tools.ex#L1)

Built-in tools for task tracking and progress management.

TodoTools allows AI agents to break down complex tasks, track progress,
and maintain focus on multi-step operations. Todos are automatically
injected into the system prompt when `enable_todos: true`.

## Setup

Enable todos when creating an agent:

    agent = Nous.new("lmstudio:qwen3-vl-4b-thinking-mlx",
      instructions: "You are a helpful assistant",
      enable_todos: true,  # Enable todo tracking
      tools: [
        &TodoTools.add_todo/2,
        &TodoTools.update_todo/2,
        &TodoTools.complete_todo/2,
        &TodoTools.list_todos/2
      ]
    )

Initial todos (optional):

    {:ok, result} = Nous.run(agent, "Build a REST API",
      deps: %{todos: []}  # Start with empty todo list
    )

## How It Works

1. Todos are stored in `ctx.deps.todos`
2. Tools return `__update_context__` to update the todo list
3. AgentRunner merges updates back into context
4. Before each model request, todos are injected into system prompt
5. AI sees current progress and can self-organize

## Example

    # AI receives complex task
    {:ok, r1} = Nous.run(agent, "Analyze codebase and create report")

    # AI breaks it down:
    # - Calls add_todo("Read all source files")
    # - Calls add_todo("Analyze dependencies")
    # - Calls add_todo("Write report")

    # AI starts working:
    # - Calls update_todo(id: 1, status: "in_progress")
    # - Reads files...
    # - Calls complete_todo(id: 1)

    # System prompt automatically shows:
    # ✅ Completed (1): Read all source files
    # ⏳ In Progress (0):
    # 📝 Pending (2): Analyze dependencies, Write report

# `args`

```elixir
@type args() :: %{optional(String.t()) =&gt; term()}
```

Tool arguments exactly as the model produced them: JSON object keys stay
strings, values are unvalidated.

# `result`

```elixir
@type result() :: %{required(atom()) =&gt; term()}
```

Tool result: an atom-keyed map. A `:__update_context__` key, when present,
is merged back into `ctx.deps` by the runner.

# `add_todo`

```elixir
@spec add_todo(Nous.RunContext.t(), args()) :: result()
```

Add a new todo item.

## Arguments

- text: The todo description (required)
- status: Initial status - "pending", "in_progress", or "completed" (default: "pending")
- priority: Priority level - "low", "medium", "high" (default: "medium")

## Returns

- success: true/false
- todo: The created todo item
- todos: Updated full todo list
- __update_context__: Context updates for AgentRunner

# `complete_todo`

```elixir
@spec complete_todo(Nous.RunContext.t(), args()) :: result()
```

Mark a todo as completed.

## Arguments

- id: Todo ID (required)

## Returns

- success: true/false
- todo: The completed todo item
- todos: Updated full todo list
- __update_context__: Context updates for AgentRunner

# `delete_todo`

```elixir
@spec delete_todo(Nous.RunContext.t(), args()) :: result()
```

Delete a todo item.

## Arguments

- id: Todo ID (required)

## Returns

- success: true/false
- todos: Updated full todo list
- __update_context__: Context updates for AgentRunner

# `list_todos`

```elixir
@spec list_todos(Nous.RunContext.t(), args()) :: result()
```

List all todos with optional filtering.

## Arguments

- status: Filter by status - "pending", "in_progress", "completed" (optional)
- priority: Filter by priority - "low", "medium", "high" (optional)

## Returns

- success: true
- todos: Filtered todo list
- total: Total number of todos
- by_status: Count by status

# `update_todo`

```elixir
@spec update_todo(Nous.RunContext.t(), args()) :: result()
```

Update an existing todo item.

## Arguments

- id: Todo ID (required)
- text: New text (optional)
- status: New status - "pending", "in_progress", "completed" (optional)
- priority: New priority - "low", "medium", "high" (optional)

## Returns

- success: true/false
- todo: The updated todo item
- todos: Updated full todo list
- __update_context__: Context updates for AgentRunner

---

*Consult [api-reference.md](api-reference.md) for complete listing*
