Skip to content
MartinsAI.
All writing
AI Engineering

What 'AI Agent' Actually Means Once You're Shipping One

Multi-channel bot delivery, versioned edit history, and a state machine underneath the chat UI — what changes when an AI feature has to be a product, not a demo.

5 min read

"AI agent" has become a label loose enough to cover a single well-crafted prompt and a genuinely stateful, tool-using system, which makes it a mostly useless word until you look at what a specific product actually needs it to do. Building the agent layer for CowriterAI — an AI-assisted academic writing tool for university students — clarified this for me by forcing three requirements that a single-prompt chatbot doesn't have to deal with: the agent has to work identically across channels the student didn't choose, it has to leave an auditable trail of what it changed and why, and it has to recover cleanly when a step fails partway through.

An agent is a workflow with state, not a prompt with tools

The distinction I keep coming back to: a chatbot responds to a message. An agent executes a workflow that happens to include model calls as some of its steps, alongside deterministic ones — fetching the student's current draft, running a plagiarism-adjacent similarity check, applying edits, and persisting a new version — that don't benefit from being non-deterministic at all.

CowriterAI's agent runs on TanStack Start with the eve framework structuring the actual workflow steps, and PayloadCMS custom Endpoints as the interface between that workflow and the CMS-backed data (student accounts, drafts, submission history). The model call for "improve this paragraph" is one step in a pipeline that also includes fetching the current draft state, validating the requested edit against academic-integrity constraints, applying the diff, and writing a new version — and only one of those steps is a language model doing something creative. Treating the whole pipeline as "the AI" obscures which parts actually need an LLM and which parts are ordinary application logic that happens to sit next to one.

Multi-channel means the workflow can't assume a chat window

Students reach the agent through a web dashboard, but also through Telegram, WhatsApp, and Messenger — channels chosen because that's where the target audience already spends time, not because a chat UI is the ideal interface for editing a five-page essay. This constrains the agent architecture more than it sounds like it should: any step that assumes rich UI (inline diffs, a sidebar showing edit history, drag targets) has to degrade to something that works as plain text in a Telegram thread, because the underlying workflow is shared across all four surfaces.

In practice this means the agent's output is structured data first — an edit proposal with a diff, a confidence signal, and a short explanation — and each channel's adapter decides how to render that structure. The web dashboard can show a rich inline diff. The WhatsApp adapter renders the same structured proposal as plain text with before/after snippets. Neither adapter talks to the model directly; both talk to the same workflow output.

interface EditProposal {
  targetSection: string;
  diff: { before: string; after: string };
  rationale: string;
  requiresConfirmation: boolean;
}

// Web renders this as an inline diff view.
// Telegram/WhatsApp adapters render it as formatted plain text
// with an inline "Apply" / "Discard" reply.

AI SDK Elements handles the chat-shaped UI on the web surface specifically — streaming responses, tool-call rendering, message threading — but it's the presentation layer for one channel, not the definition of the agent.

Versioned edits are the difference between a feature and a liability

An AI system that edits a student's academic submission and can't show what it changed, or can't be rolled back, isn't a feature you want to ship into an academic context — it's a dispute waiting to happen the first time a student's original argument gets altered by a suggestion they didn't fully review before accepting. Payload's Versions feature gives every AI-driven edit a full history against the submission: what the draft looked like before, what the agent proposed, and what the student actually accepted, each as a distinct version rather than a single overwritten "current" field.

This matters for a mundane reason as much as an ethical one: students revise essays non-linearly. Being able to answer "what did this paragraph look like before the AI touched it" or "did I actually accept that suggestion" needs to be a lookup, not a reconstruction from logs.

Failure has to be a first-class state, not an afterthought

The workflow steps that aren't model calls — fetching a draft, running a check, persisting a version — can fail in ordinary ways: a database timeout, a validation failure, a duplicate submission. The steps that are model calls fail in less ordinary ways: a response that doesn't parse into the expected structure, a rate limit, a completion that technically succeeds but doesn't satisfy the task ("edited" text that's just the original with different whitespace).

Treating every one of these as "the AI request failed, show a generic error" is where agent products lose trust fastest. The workflow needs enough state tracking to know which step failed and resume from there — re-running the model call on a transient failure without re-fetching a draft that already loaded correctly, versus surfacing a specific, actionable message when the failure is a validation rule the student's request actually violated (asking the agent to rewrite a section in a way that would trigger an academic-integrity flag, for instance) rather than a generic retry prompt that doesn't tell the student anything useful.

None of this requires more sophisticated models. It requires treating the thing you're building as a workflow with well-defined steps, explicit state, and observable history — where a language model call is one kind of step among several, not the architecture itself. That reframing is what "agent" should mean once you're past the point of a demo.

AI AgentsTanStack StartPayload CMSAI SDK