Resources
What we are building, and what we have learned building it.
The normal way a coding agent gets access to a service is that you paste a key into your terminal. That habit is the reason credential theft works, and we all have it.
A new project cannot answer anything and cannot index anything, because it has no models. That is correct and it is also the least helpful possible starting state, so the interesting design question is what it tells you about itself.
A streamed turn that fails answers 200. It has to — the failure is a frame inside a body that had already started. Which means it appears in no access log, no 5xx count, and no HTTP-level alert you have built.
We shipped a product whose pitch is an agent that retrieves, browses, remembers and calls your systems. Then an answer built on a web page, an MCP server, or something the user said last week came back with citations: [], claims: [], attribution: "none" — and the [2] in the reply really was the m…
Subagents are the feature that demos best and costs most. Nine files audited in parallel looks like magic in a screen recording, and every one of those nine is a full model loop billed to you.
A bookkeeping assistant. Blocked topic: "personal tax advice", which is a perfectly reasonable thing not to want your product doing. It caught "What is the mileage rate for 2026?" — a company reimbursement rate, and about the most on-domain question that corpus could be asked.
Asked for a diagram of four SLA tiers, a project whose corpus says 24 hours / 3 days / 14 days / 90 days got back a tidy PNG labelled "1 hour / 4 hour / 12 hour / 24 hour". content came back empty. guardflags was [].
Replaying the whole transcript works until it doesn't. Then every later turn fails with "context length exceeded" — and it keeps failing, because the message that tipped it over is still in the history.
Your domain knowledge has exactly one home, and it is loaded on every turn whether relevant or not. So it grows. Every behaviour change becomes a global change, and eventually nobody can edit what the agent does without touching the one string everything else depends on.
A client-side tool runs in your application's process, which is exactly the right place for it — until there is no application process. Then the same agent, with the same permissions, on the same account, simply cannot do the thing.
The tool was called cancelbooking. Its description read: "Cancel a booking. Irreversible: the slot is released to the market immediately." The project granted approvals. There was an onApproval handler that refused everything. It was never once consulted.
A user typed "close every berth for July", thought better of it, hit stop. A minute later they asked what time it was. They got both.
The first time someone reported this I did not believe it was a bug. A question, forty seconds of thinking, a train going into a tunnel, and the answer was gone — not delayed, gone, and they had been billed for it.
A customer asks what their AI usage cost last month. You have exactly one number: the provider invoice. It does not split by customer, by feature, or by user. So you guess — and you either eat margin quietly or overcharge somebody who will eventually check.
Almost everyone gets retrieval scoping right. The agent cannot read the wrong customer's documents. Then it calls a tool, and the tool goes and fetches them, because the tool runs as your service account and nobody re-checked.
Spinning up a Linux box and letting a model run commands in it takes an afternoon. Everything after that afternoon — the file it edits without reading, the export that never reaches the user, the sandbox nobody cleaned up — is where the months go.
A scheduled agent run asked for permission to archive a record. Nobody was there. The turn stopped. The task reported status: "completed", runcount: 1, lasterror: null — which is byte-for-byte what a run that did the work reports.
I spent three years building AI features for other people's products. The thing that cost me the most sleep was never the model. It was a citation that used to be right.
