Todos
The todo module enables Loquent to autonomously create and execute tasks from phone call transcriptions. After a call ends, an LLM analyzes the transcription, extracts actionable items matching predefined types, and queues them for human review. Approved todos execute automatically using system tools.
How It Works
Section titled “How It Works”Call ends → Transcription saved → extract_todos(call_id, org_id) LLM analyzes transcription against org's TodoTypes → Creates todos with status "pending_review"
User reviews in dashboard → Approve or Reject
Every 30 seconds: → execute_todos_job picks up "approved" todos → execute_todo(todo_id) LLM agent runs with system tools (e.g. send email) → Status: "completed" or "failed"Core Concepts
Section titled “Core Concepts”TodoType (Template)
Section titled “TodoType (Template)”An org-defined category of task. Tells the system what kinds of actions to look for in call transcriptions.
pub struct TodoType { pub id: Uuid, pub name: String, // e.g. "Follow-up Email" pub description: String, // What this type of task does pub tools: Vec<SystemTool>, // Which system tools to use during execution}Todo (Instance)
Section titled “Todo (Instance)”A specific task extracted from a specific call, linked to a TodoType.
pub struct Todo { pub id: Uuid, pub call_id: Option<Uuid>, pub type_id: Uuid, pub type_name: String, // Denormalized from TodoType pub description: String, // LLM-generated context for this specific task pub status: String, pub error_message: Option<String>, pub created_at: String, pub completed_at: Option<String>,}Status Lifecycle
Section titled “Status Lifecycle”| Status | Meaning |
|---|---|
pending_review | Extracted by LLM, awaiting human approval |
approved | Human approved, queued for execution |
rejected | Human rejected, no action taken |
in_progress | Currently being executed by the AI agent |
completed | Executed successfully |
failed | Execution failed — check error_message |
Todo Extraction
Section titled “Todo Extraction”extract_todos runs after a call transcription is saved.
Inputs: call_id, organization_id
Flow:
- Fetch the call and its transcription
- Load all
TodoTypes for the org (exits early if none defined) - Send transcription to GPT-5 with structured output, asking it to identify actionable items matching the available types
- Each extracted item includes a
type_id(UUID) anddescription - Validate each
type_idagainst the org’s types — skip unknown IDs - Insert valid todos with status
pending_review
LLM prompt:
System: You are analyzing a phone call transcription to extract actionable to-do items.
Available to-do types:- ID: <uuid> Name: <name> Description: <description>
For each actionable item you find, add it to the todos array.Only extract to-dos that match one of the available types.If no actionable items are found, return an empty todos array.
User: <transcription text>The response is constrained to a JSON schema (ExtractedTodos { todos: Vec<ExtractedTodo> }).
Todo Execution
Section titled “Todo Execution”The execute_todos_job runs every 30 seconds, picking up all todos with status approved.
For each todo, execute_todo runs:
- Guard: reject if status isn’t
approved - Set status to
in_progress - Load the TodoType and its assigned system tools
- Fetch call transcription for context (if linked to a call)
- Run an LLM agent (GPT-5) with the tools, capped at 10 tool-calling steps
- On success: set
completed+completed_at - On failure: set
failed+error_message
Todos execute sequentially. The in_progress status prevents duplicate execution if the job fires again while a todo is still running.
System Tools
Section titled “System Tools”SystemTool is an enum of constrained actions the AI can invoke during execution. The AI provides parameters, but sensitive values (like email recipients) come from the system.
| Tool | What It Does |
|---|---|
SendEmailToCaller | Sends a follow-up email to the caller’s contact |
SendEmailToCaller Flow
Section titled “SendEmailToCaller Flow”- Look up the call’s
contact_id - Find the contact’s preferred email from
contact_emailtable - GPT-5 composes subject and body using the task description and call transcription
- Send via
bases::email::send_email
API Endpoints
Section titled “API Endpoints”All endpoints require an authenticated session.
| Route | Method | Description |
|---|---|---|
/api/todos | GET | List all org todos (newest first) |
/api/todos/{id}/approve | PUT | Approve a pending todo |
/api/todos/{id}/reject | PUT | Reject a pending todo |
Approve and reject only work on todos with status pending_review.
Todo Types
Section titled “Todo Types”| Route | Method | Description |
|---|---|---|
/api/todo-types | GET | List all org todo types with tools |
/api/todo-types/{id} | GET | Get a single todo type |
/api/todo-types | POST | Create a todo type |
/api/todo-types/{id} | PUT | Update name, description, and tools |
/api/todo-types/{id} | DELETE | Delete a todo type (hard delete) |
Create and update accept TodoTypeData:
pub struct TodoTypeData { pub name: String, pub description: String, pub tools: Vec<SystemTool>,}Tool updates use a delete-all-then-reinsert strategy on the todo_type_tool join table.
Module Structure
Section titled “Module Structure”src/mods/todo/├── api/ # CRUD for todos and todo types├── components/ # UI: todo list, cards, type management├── jobs/ # execute_todos_job (every 30s)├── services/ # extract_todos, execute_todo├── types/ # Todo, TodoType, TodoData, SystemTool├── utils/ # send_email_to_caller└── views/ # TodoListView, TodoTypeListView, CreateTodoTypeView, TodoTypeDetailsViewRelated Modules
Section titled “Related Modules”- Call — todos are extracted from call transcriptions
- Agent — agents handle the calls that generate todos
- Supporting Modules — dashboard shows todo status distribution