Releases: agentailor/cameron
Release list
v1 — Cameron is born
Meet Cameron: a personal finance agent you own and run yourself. This is the first release where Cameron stops being a generic chat starter and becomes itself — a named agent with a persona, its own system of record, and finance tools that never touch your money without asking.
Built in public alongside the Agentailor blog — one tagged release per article. v1 is the "Meet Cameron" chapter.
What's new in v1
🧑💼 Cameron's identity & hard rules
A pragmatic, numbers-first finance persona — never moralizes about spending. Three rules that never relax:
- Never moves money or mutates financial records without explicit human approval.
- Every capability — built-in, connector, or future skill — passes the same approval gate.
- Your financial data stays on infrastructure you control.
💸 A transaction store you own
Cameron's system of record: a Postgres-backed transaction table (amounts in minor units, expense/income, account, category, source + dedup provenance) plus categories. External sources normalize into it — they're never read live — so every tagged version stays reproducible on seed data.
🛠️ Finance tools (approval-gated where it matters)
log_expense— record a transaction (gated: pauses for your approval)query_transactions— list/filter transactions (read-only)describe_finance_schema+run_sql— answer analytical questions (totals, top-N, group-by) via guarded, SELECT-only SQL: static validation plus a realREAD ONLYtransaction with a statement timeout, always rolled back, row-capped (read-only)list_categories/create_category— manage categories (create is gated)inspect_csv+import_transactions_csv— a two-step CSV import handshake that never streams your rows through the model; the agent proposes a column mapping for approval, and the import runs entirely server-side (import is gated)
📥 Import that fails loud, not silent
Bank/export CSVs (including localized headers) import via an explicit, agent-proposed mapping. If a mapping names a column that isn't in your file, the import errors and writes nothing rather than silently dropping the field. Dates are parsed by a confirmed format — never guessed — and unparseable rows are reported, not quietly stamped with today's date.
🔒 Human-in-the-loop, narrowed to mutations
Reads and MCP tools run without interruption; only mutating tools pause for approve/deny. Approvals are batched and each denial can carry an explanation back to the agent.
Under the hood
- Agent: LangChain/LangGraph v1
createAgent(prebuilt ReAct) +humanInTheLoopMiddleware - Persistence: Postgres via Drizzle behind a repository seam; conversation history via the LangGraph Postgres checkpointer
- Providers: Anthropic (default), OpenAI, Google
- Plus everything from the v0 foundation: dynamic MCP tool loading, SSE streaming, multimodal uploads (MinIO/S3), Langfuse observability, OpenAPI docs
Getting started
git clone https://github.com/agentailor/cameron.git
cd cameron
docker compose up -d # Postgres + MinIO
pnpm install
pnpm db:migrate
pnpm db:seed # 6 demo categories + a few months of sample transactions
pnpm dev # http://localhost:3100Seeded from the fullstack-langgraph-nextjs-agent starter.
What's next
v2 — Memory: budgets and preferences as long-term memory, plus summarization of aging history.