Enable and configure
Set AI_PROVIDER and its matching secret, then enable ai.assistant. Both gates are required. AI_MODEL can override the provider default. Secrets remain server-side. The existing MCP server works without a configured AI provider.
The default request limits are five model/tool steps, 2,048 output tokens per model call, a 60-second abort deadline and ten requests per minute per User. Input and history are separately bounded. These per-request limits do not replace provider account spending controls.
One catalog
catalog.schema.ts defines Zod tool contracts; catalog.ts binds authorized implementations. The assistant and MCP adapt those same operations. Each call checks current Organization membership. The assistant uses the Session's Active Organization and rejects a change during a turn.
The catalog has 23 tools. Read operations include todo_list, todo_detail, files_list, whoami, search, fetch, document_read and organization_info, plus AutoFolio's garage tools: garage_cars, costs_summary, costs_compare, vehicle_tco, net_worth, upcoming, sale_estimate (the deal result at the estimated value, an estimate) and expense_draft (a draft the User saves in Add expense; it writes nothing). Garage results carry every amount formatted for the account and the app screen with the details; the mobile assistant links each answer to that screen. Approved writes are todo_create, todo_complete, import_start, create_todo_draft, draft_task_plan and propose_review; ask_for_input pauses for a User choice.
files_list exposes confirmed file IDs and conversion status. document_read returns two chunks by default, at most four of 8 KiB each, and nextCursor for another page. Search ranks converted text alongside Todos and filenames. Original file bytes never enter tool results. An awaitingBrowser result means the User must finish preparation in Files. Reading Document Text sends the selected chunks to the configured model provider and stores the results in the Thread. Treat source text as untrusted data and disclose partial reads. See documents.
Every write needs approval bound to its User, Organization, tool name and parsed arguments. Assistant approvals also bind the Thread and call ID. The execution transaction checks current membership and expiry, applies the change, records its audit and stores the result. A replay returns that result rather than repeating the mutation.
Copilot cards
With ai.genui on, the mobile assistant draws each garage tool result as a fixed card instead of quoting it (ADR-0018, Plan B of the AI features spec §3; OpenUI was evaluated and set aside). The result schemas live in @autofolio/api/assistant/contract; threadView parses each one against its schema and drops anything else.
- Copilot-Costs (
costs_summary): the period's total, its change against the span before, the months as bars and the three biggest categories; "See costs" opens Finances. Chips suggest the next question. - Copilot-Compare (
costs_compare,sale_estimate): cost per km or mile and per month per car; the sale at the estimated value with its source, the loan and the deal result (estimate); Prepare sale opens M-Vender. - Copilot-Draft (
expense_draft): the draft's amount, volume, date, reading and vendor, the economy of the tank it closes; Review and save opens Add expense prefilled, Discard hides it. Nothing is saved before the User saves (RN10). - TCO, net worth, what is due and the car list have their own cards. Every card names its source and opens its screen.
The app sends cards: true, so the server (with the flag on) asks the model for a sentence or two rather than every number. The dev links autofolio://dev/Copilot-Costs, Copilot-Compare and Copilot-Draft ask the board's question in a new conversation; they need a provider, ai.assistant, and spend a question of the quota.
Streaming and persistence
TanStack AI owns the native Promise/SSE lifecycle. The HTTP boundary owns input limits, auth, cancellation, the Thread lease and its bounded pool. Persistence snapshots at most once per second and saves the finished transcript. Stop, timeout or disconnect aborts the turn; reopening recovers the last saved state and pending interrupts.
There is no disconnected background run or resumable transport. Text after the last snapshot can be lost. Deleting a Thread deletes its messages and linked approvals but does not undo completed domain changes.
Extend
Add a catalog contract and authorized operation once, then adapt through the existing assistant/MCP consumers. Preserve exact-argument approval and replay protection. Tests use the deterministic adapter only in an ai-test build plus AI_TEST_PROVIDER=true; never publish that build. Read ADR-0007 before changing transport, approvals or persistence.
Key files
packages/api/src/features/agent-tools/agent-tools.catalog.tspackages/api/src/features/agent-tools/agent-tools.contract.tspackages/api/src/features/assistant/assistant.http.tspackages/api/src/features/agent-tools/agent-tools.approvals.tspackages/api/src/features/assistant/assistant.threads.tsscripts/test-local-ai.mjs