| name | integrate-todo-list |
| description | MUST be used whenever adding a task/todo list feature to a Flows app with Atlas chat. Do NOT manually create todo state management or tool definitions — this skill handles the full module (context, provider, tool, hooks, UI components) and all integration wiring. Prerequisite: integrate-atlas-chat must already be set up. Triggers: todo list, task list, task tracking, TodoWrite, todo panel, task panel, progress tracking, add todos, add tasks. |
| allowed-tools | Read, Glob, Grep, Edit, Write, Bash |
Integrate Todo List
Add a structured task-tracking feature to this Flows app. The agent will use a TodoWrite tool
to create and update a task list as it works through multi-step queries, giving the user real-time
visibility into what the agent is doing and why.
Prerequisite: integrate-atlas-chat must already be complete — useAtlasChat must be wired (typically from ./atlas-agent/react), src/atlas-agent/ must contain the vendored atlas-agent sources, and @sinclair/typebox must be installed per that skill.
Step 1 — Read the app
Before writing anything, read:
package.json — confirm @tabler/icons-react is installed; if not, install it with the app's package manager
src/App.tsx — find where to add TodoProvider
- The file that calls
useAtlasChat (likely src/chat/useChatViewModel.ts or src/App.tsx) — this is where the tool gets wired
- The chat view component that renders messages — this is where
TodoPanel and TodoToolResultCard go
Step 2 — Create the src/todo/ module
Find the skill directory by running find . -path "*/.agents/skills/integrate-todo-list/code" -type d from the project root.
Read each file from <skill-dir>/code/ and write it into src/todo/ with the same filename:
| File | Purpose |
|---|
types.ts | TodoItem and TodoList types |
TodoContext.tsx | React context + TodoProvider |
useTodoList.ts | Hook to read/write the todo list |
todoWriteTool.ts | createTodoWriteTool factory — AtlasTool with full CDF task-decomposition guidance |
useTodoWriteTool.ts | Hook that memoizes the tool with current state access |
TodoPanel.tsx | Card UI: progress bar + task rows |
TodoItemRow.tsx | Single row with animated status icons |
TodoToolResultCard.tsx | Compact summary card for tool call display |
All files use relative imports (./types, ./TodoContext, etc.) — no changes needed.
Step 3 — Wrap the app in TodoProvider
In src/App.tsx (or the root component), wrap the existing tree with <TodoProvider>:
import { TodoProvider } from './todo/TodoContext';
function App() {
return (
<TodoProvider>
{/* existing children */}
</TodoProvider>
);
}
Step 4 — Wire the tool into useAtlasChat
In the file that calls useAtlasChat, add the following. Adjust import paths to match the app's conventions.
import { useRef, useCallback } from 'react';
import { useTodoList } from './todo/useTodoList';
import { useTodoWriteTool } from './todo/useTodoWriteTool';
const { todos, setTodos } = useTodoList();
const todoWriteTool = useTodoWriteTool();
const todosRef = useRef(todos);
todosRef.current = todos;
const getAppContext = useCallback(() => {
const t = todosRef.current;
if (t.length === 0) return undefined;
const lines = t.map((item, i) => `${i + 1}. [${item.status}] ${item.content}`);
return `Current todo list:\n${lines.join('\n')}`;
}, []);
const { messages, send, isStreaming, progress, error, reset, abort } = useAtlasChat({
client: isLoading ? null : sdk,
agentExternalId: AGENT_EXTERNAL_ID,
tools: [todoWriteTool],
getAppContext,
});
const handleReset = useCallback(() => {
reset();
setTodos([]);
}, [reset, setTodos]);
return { ..., todos };
Step 5 — Render TodoPanel in the chat view
In the component that renders the chat input area, add <TodoPanel> above the input field:
import { TodoPanel } from './todo/TodoPanel';
<TodoPanel todos={todos} />
<YourChatInput ... />
TodoPanel returns null when the list is empty, so it's safe to always render it.
Step 6 — Render TodoToolResultCard for tool call steps
In the component that renders per-message tool calls (typically a steps accordion or similar), branch on the tool name:
import { TodoToolResultCard } from './todo/TodoToolResultCard';
{toolCalls.map((tc, i) =>
tc.name === 'TodoWrite' ? (
<TodoToolResultCard key={i} toolCall={tc} />
) : (
<YourDefaultToolCallCard key={i} toolCall={tc} />
)
)}
Step 7 — Verify
Run the app's type-check command (typically pnpm tsc --noEmit) and confirm there are no errors.
If the project has tests, run them to confirm nothing regressed.
Done
The agent can now use TodoWrite to create and track tasks. It will:
- Show a task panel as soon as it starts multi-step work
- Update task status in real-time (
pending → in_progress → completed)
- Clear the list automatically when all tasks are done
- Inject the current task list into each prompt via
getAppContext so it knows where it left off