{"id":"3e17bfee-419d-4d40-bb40-5f8f67724754","slug":"cameron","kind":"skill","name":"cameron","summary":"Cameron — a personal finance agent you own and run yourself. Built in public alongside the Agentailor blog, one tagged release per article.","owner":"agentailor","repoUrl":"https://github.com/agentailor/cameron","license":"MIT","licenseTier":"permissive","trust":"community","stars":2,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-07-21T07:58:12.000Z","addedAt":"2026-10-21T21:33:55.854Z","logoUrl":"https://avatars.githubusercontent.com/u/223515933?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["data-analytics","writing"],"tags":[],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-21T21:34:16.246Z","sample":false,"url":"https://conduits.dev/tools/cameron","language":"TypeScript","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Cameron\n\n> **A personal finance agent you own and run yourself.** Built in public alongside the\n> [Agentailor](https://blog.agentailor.com) blog — one tagged release per article.\n\n![Cameron — approval gate](docs/images/hero-approval.png)\n\n_Cameron asks before it writes. Every time, for every capability._\n\n[![Release](https://img.shields.io/github/v/release/agentailor/cameron?label=release&color=f59e0b&logo=github)](https://github.com/agentailor/cameron/releases/latest)\n[![CI](https://img.shields.io/github/actions/workflow/status/agentailor/cameron/ci.yml?label=ci&logo=github)](https://github.com/agentailor/cameron/actions)\n[![TypeScript](https://img.shields.io/badge/TypeScript-6.0-blue?logo=typescript)](https://www.typescriptlang.org/)\n[![Next.js](https://img.shields.io/badge/Next.js-16.2-black?logo=next.js)](https://nextjs.org/)\n[![LangGraph](https://img.shields.io/badge/LangGraph.js-1.4-green?logo=langchain)](https://langchain-ai.github.io/langgraphjs/)\n[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16+-blue?logo=postgresql)](https://www.postgresql.org/)\n\n---\n\n## What Cameron is\n\nCameron tracks spending, imports bank exports, answers questions about where the money went, and\n— over the arc of the series — learns to build its own capabilities. It runs on your machine,\nagainst your Postgres, with your API key.\n\nIt's built for two audiences at once: the **owner**, who dogfoods it daily on real finances, and\nthe **reader**, a developer learning agent engineering by running Cameron against seed data.\n\n### Three rules, never relaxed\n\n1. **Cameron never moves money or mutates financial records without explicit human approval.**\n2. **Every capability passes the same approval gate** — built-in, skill, connector, or\n   self-written. No exceptions, no allowlist.\n3. **All financial data stays on infrastructure the owner controls.**\n\nThese aren't aspirations. Rule 1 is enforced by a human-in-the-loop interrupt in the graph; rule 2\nby a single `MUTATING_TOOL_NAMES` list that the middleware and the capabilities page both read;\nrule 3 by the fact that nothing ships to a hosted backend — the database is yours.\n\n---\n\n## What it looks like\n\n<table>\n  <tr>\n    <td align=\"center\" width=\"50%\">\n      <img src=\"docs/images/approval-gate.png\" alt=\"Approval gate\" width=\"440\" />\n      <br /><strong>The approval gate</strong>\n      <br />Nothing is written until you approve it.\n    </td>\n    <td align=\"center\" width=\"50%\">\n      <img src=\"docs/images/run-sql.png\" alt=\"SQL tool call\" width=\"440\" />\n      <br /><strong>Ask anything, in SQL</strong>\n      <br />Read-only queries, shown as written and as run.\n    </td>\n  </tr>\n  <tr>\n    <td align=\"center\" width=\"50%\">\n      <img src=\"docs/images/capabilities.png\" alt=\"Capabilities page\" width=\"440\" />\n      <br /><strong>Every capability, listed</strong>\n      <br />What Cameron can do, and what needs your approval.\n    </td>\n    <td align=\"center\" width=\"50%\">\n      <img src=\"docs/images/csv-import.png\" alt=\"CSV import\" width=\"440\" />\n      <br /><strong>Import your bank export</strong>\n      <br />Cameron proposes the mapping; you confirm it.\n    </td>\n  </tr>\n</table>\n\n---\n\n## Skills: instructions loaded on demand\n\nCameron's know-how doesn't all live in the system prompt. A **skill** is a folder in\n[`skills/`](skills/) holding a `SKILL.md` — instructions in the\n[AgentSkills](https://agentskills.io/specification) format. Only each skill's name and description\nsit in the prompt; the agent calls `load_skill` to pull the full body into context when it decides\nthe skill is relevant. That's progressive disclosure: the instructions cost you nothing until\nthey're being used.\n\n![Cameron drawing a report from the expense-reporter skill](docs/images/cameron-report-exporter.png)\n\n_Asked for an evolution chart, Cameron loads `expense-reporter`, queries the monthly totals, and\ndraws the chart the skill told it to pick._\n\nAdding one is a file, not a code change — create `skills/<name>/SKILL.md` with `name` and\n`description` frontmatter and restart. An invalid skill is dropped and logged; the valid ones still\nload, and an empty `skills/` directory is not an error.\n\n**Reading a skill approves nothing it tells you to do.** `load_skill` is read-only, so it\nauto-approves — but the instructions it returns reach mutating tools through the same gate as\neverything else. Rule 2 holds: the approval boundary does not move because the agent read\nsomething first.\n\nSee [docs/SKILLS.md](docs/SKILLS.md) for the validation rules, the failure policy, and why\n`skills/` (shipped product code) is not `.agents/skills/` (gitignored dev tooling).\n\n---\n\n## Quick start\n\n### Run it (Docker only)\n\n**Prerequisites:** Docker, and a model to talk to — an API key for Anthropic, OpenAI or Google, or\nany **OpenAI-compatible** endpoint (Ollama, vLLM, LM Studio, Groq, OpenRouter, DeepSeek). A local\nruntime needs no key at all; you point Cameron at its base URL in Settings.\n\nYou pick the provider and model **in the app**, not in the environment — with nothing chosen\nCameron says it's unconfigured rather than guessing. `.env` only ever holds the keys.\n\n```bash\ngit clone --branch v4 https://github.com/agentailor/cameron\ncd cameron\n\ncp .env.example .env              # add your model API key, if your provider needs one\ndocker compose --profile full up  # http://localhost:3100\n```\n\nThat builds the app, waits for Postgres, applies migrations, and starts everything. Nothing but\nDocker is needed on your machine.\n\n> **Why `--branch v4`?** Tags are the stable points — each one matches a published article and has\n> passed CI before release. `main` is the working trunk and runs ahead of the latest tag between\n> articles, so it may carry half-finished work. Clone the [latest\n> release](https://github.com/agentailor/cameron/releases/latest) to start from something known\n> good; `git checkout main` if you want what's in flight.\n\nThis is the stack that holds your real financial records — its Postgres (`:5546`) and MinIO\n(`:9102`) are separate containers on separate volumes from the dev stack below, so working on\nCameron can't disturb your data. Stop it with `docker compose --profile full down`; adding `-v`\nto that command **deletes your financial data**.\n\n### Work on it (app on the host)\n\n**Prerequisites:** the above, plus Node 20+ and pnpm.\n\n```bash\npnpm install\ncp .env.example .env       # add your model API key, if your provider needs one\ndocker compose up -d       # dev dependencies — Postgres :5544, MinIO :9100/:9101\npnpm db:migrate\npnpm dev                   # http://localhost:3100\n```\n\nThis stack is disposable: it serves `mydb_dev` on its own volumes, and `docker compose down -v`\nresets it without touching anything above.\n\nThen ask it something — _\"what did I spend on dining last month?\"_ — or drop in a CSV export and\nlet it propose a column mapping.\n\nThe tests are free and offline: `pnpm test` runs with no model, no network and no database.\n\n---\n\n## Built in public, one tag per article\n\nCameron ships as a linear series of tagged releases — `v1`, `v2`, `v3`, … — one (or two) per\narticle. Reading about a topic? Check out the tag for the article that taught it:\n`git checkout v1`. The release badge above points at the newest tag, and\n[`release.yml`](.github/workflows/release.yml) gates every `v*` tag on the test suite and a\ntypecheck, so a tag is a point that built and passed.\n\n`main` is where the next version is assembled, so it sits **ahead** of the newest tag and can carry\nwork that isn't finished yet. That's what a trunk is for — but it means the tag, not `main`, is the\nplace to start if you want Cameron to behave the way an article describes.\n\nThe series opens with **[`v1`: Cameron is born](https://github.com/agentailor/cameron/releases/tag/v1)**\n— the persona and hard rules, a transaction store you own, approval-gated finance tools, and CSV\nimport. It's the first release where Cameron stops being a generic chat starter and becomes\nitself.\n\n📖 **[Follow the series →](https://blog.agentailor.com/cameron)**\n\n---\n\n## Documentation\n\nThe technical detail lives in [`docs/`](docs/) rather than here:\n\n| Doc                                       | What's in it                                                                                                                                            |\n| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [ARCHITECTURE.md](docs/ARCHITECTURE.md)   | System overview, agent workflow, data flow, database schema, MCP integration, approval process, streaming, **project structure**, **available scripts** |\n| [SKILLS.md](docs/SKILLS.md)               | How skills load, the validation rules, and how they're packaged for production                                                                          |\n| [TESTING.md](docs/TESTING.md)             | Why the unit suite stays free and offline, and what belongs in evals instead                                                                            |\n| [API.md](docs/API.md)                     | The generated OpenAPI spec, served at `/api/openapi` and browsable at `/api-docs`                                                                       |\n| [OAUTH.md](docs/OAUTH.md)                 | OAuth for MCP servers that need it                                                                                                                      |\n| [OBSERVABILITY.md](docs/OBSERVABILITY.md) | OpenTelemetry tracing to a self-hosted backend (Phoenix by default), what a trace contains, and swapping backends                                       |\n| [eval/README.md](eval/README.md)          | The paid, non-deterministic eval suite — never in CI                                                                                                    |\n\n[AGENTS.md](AGENTS.md) carries the conventions a coding agent needs to work in this repo.\n\n---\n\n## Built on a starter\n\nThe foundation Cameron builds on — the chat loop, streaming, persistence, dynamic MCP tool\nloading, human-in-the-loop approvals, and multi-model support — comes from\n[`fullstack-langgraph-nextjs-agent`](https://github.com/agentailor/fullstack-langgraph-nextjs-agent),\na generic LangGraph.js + Next.js agent starter.\n\nThat inherited base is referred to as **v0** throughout these docs. It is not a Cameron release\nand carries no `v0` tag — Cameron's own history starts at `v1`. The starter keeps its job as the\nreusable scaffold; full credit and thanks to it.\n\nCameron is part of **[Agentailor](https://agentailor.com)**, the hub for developers building AI\nagents. It's the Path 1 flagship — _build it yourself, own every layer_.\n\n---\n\n## Contributing\n\nIssues and pull requests are welcome. Before opening a PR:\n\n```bash\npnpm test          # must pass, and must stay free/offline\nnpx tsc --noEmit   # must be clean\npnpm format        # Prettier\n```\n\nNew tools ship with their test in the same commit — see [TESTING.md](docs/TESTING.md) for why\nthat rule exists.\n\n---\n\n## Need help taking this to production?\n\nI help teams design and optimize LangGraph-based AI agents (RAG, memory, latency, architecture).\nIf you're building something serious on top of this and want hands-on help,\n[DM me on LinkedIn](https://www.linkedin.com/in/ali-ibrahim-junior/) — happy to jump on a short\ncall.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n### Acknowledgments\n\n- [`fullstack-langgraph-nextjs-agent`](https://github.com/agentailor/fullstack-langgraph-nextjs-agent) — the starter Cameron's v0 foundation is seeded from\n- [LangChain](https://github.com/langchain-ai) for LangGraph.js\n- [Model Context Protocol](https://modelcontextprotocol.io/) for the tool integration standard\n- [Next.js](https://nextjs.org/) for the framework\n\n---\n\n**Follow Cameron as it grows, one release at a time.** →\n[the series](https://blog.agentailor.com/cameron)\n"}