The Brief
A client came to me with a deceptively simple sentence: they wanted their product to help each user reach a personal objective — something that plays out over weeks or months, not over a single conversation.
Every proposal they had received described a chatbot. Chatbots are the wrong shape for this, and the reason is not technical snobbery. A chatbot is a function: message in, message out, and the interaction is over. An objective pursued over three months is a process — it has a state that outlives every conversation, it must act while nobody is watching, and it has to be able to say what happened last Tuesday and why.
So we did not build an agent. We built an engine that pursues Goals, and treated the chat as one interface on top of it.
What "Goal, Not Prompt" Actually Means
In the usual approach, the developer writes a system prompt and hopes the model behaves. In this one, the developer declares an objective: a name, an intent in plain language, the criteria that would make it a success, and an explicit list of what the system is allowed to do on the user's behalf.
The Goal is not the actor. It is a written intention plus a complete, replayable record of everything that happened while pursuing it. The runtime does the planning, the executing, the measuring and the replanning. The model reasons at a handful of named points — it proposes a plan, judges whether a criterion is met, extracts a fact, drafts a message — and the engine validates every single proposal before anything real happens.
The practical payoff is one that matters to a non-engineer: you can ask the system why it did something, and get an answer, because the answer was recorded rather than reconstructed after the fact.
Decision 1 — Deterministic First
Scheduling, permissions, execution, progress computation, lifecycle transitions: all of that is ordinary code. None of it goes through a model.
This is the decision people push back on most, and it is the one I would defend the hardest. A language model is excellent at judgement and terrible at bookkeeping. The moment you let it decide whether a step already ran, you have built a system whose behaviour you cannot reproduce twice. Keeping the plumbing deterministic means a bug is a bug — findable, fixable, and gone once fixed — rather than a tendency.
Decision 2 — Everything Is an Event
Nothing in the system is written directly. Every visible state is a projection over an append-only log of what happened, and it can be rebuilt from scratch after a restart.
That sounds like an internal detail until the day a user asks why they were contacted, or the client asks what the system did over the weekend. With a log, both are a query. Without one, both are an apology.
It also makes the whole thing testable in a way agent systems usually are not: you replay the log and you get the same result. That is how the engine has a real test suite instead of a folder of screenshots.
Decision 3 — Permissions Can Only Tighten
A Goal can spawn a child Goal. A component can ask to be allowed more. An untrusted caller can hand in its own specification. In every one of those cases, the result can only ever narrow what was granted — never widen it, and never by leaving something out.
This is the rule that lets an autonomous system touch anything irreversible. Sending an email, charging a card, writing to a customer's record: each is declared, each carries whether it needs a human to approve it, and no clever chain of delegation can quietly upgrade its own rights. Security by omission is the failure mode of every permissive system, and the only reliable cure is to make omission mean less, never more.
Decision 4 — Cost Is an Architectural Constraint, Not a Bill
A system that runs for months, on its own, cannot be allowed to reason freely. So reasoning is routed down a deliberate ladder: a deterministic rule if one applies, then a cached decision, then a cheap model, then an expensive one, then a human — with a recorded cost for every step and a hard ceiling that stops the Goal rather than the invoice.
I have watched an unpriced model turn a modest monthly spend into a number nobody expected, on a different project entirely. Since then I treat the cost ledger as a first-class part of the domain, not as something the finance team discovers later.
What I Would Do Differently
I would build the introspection surface earlier. The engine got a command line and a visual inspector well after the core was working, and for a few weeks the only way to understand a Goal's behaviour was to read the event log by hand. Every day of that was slower than the day it would have cost to build the viewer.
I would also resist the pull toward making the model do more. Every time something was hard, the tempting fix was to hand it to the model and let it figure it out. That works in a demo and rots in production. The times I resisted are the parts of the system I still trust.
The Part That Generalises
The client got software that pursues objectives over months, explains itself, and cannot exceed the permissions it was given. The engine behind it stays theirs.
What generalises is the framing, and it is worth saying plainly to anyone weighing an AI project: the interesting question is almost never "which model". It is what the system is allowed to do, what it records, what happens when it is wrong, and what it costs to run for a year. Those four answers determine whether you end up with a product or a demo. The model, by now, is the easy part.