AI Agents in Production
Pathrule4 Rules • 2 Memories • 1 Skill
An agent is a loop: the model plans, calls a tool, reads the result, and continues until it is done or until something stops it. Almost every production failure is in that last clause. A loop with no step limit, no cost ceiling, and no stall detection burns a budget on a task it cannot finish; a tool surface that is too large or too granular produces wrong calls; and a write tool with no approval gate eventually does something irreversible to real data. This bundle covers loop bounds, tool design, privilege and approval, context discipline against prompt injection, and the tracing and evals that make behaviour reviewable.
Suggested path map
Pathrule places each piece on the matching path, so your assistant only sees it where it belongs. This is the scoping you get on import; you can adjust it in your workspace.
Rules
4Bound every loop by steps, cost, and time/src/agenthighstrictThe loop has a maximum step count, a token or money budget, a wall-clock timeout, and stall detection, and it reports why it stopped.
| 1 | An agent loop is the only code in your system whose termination depends on a model's judgment. Give it limits that do not. |
| 2 | |
| 3 | - Set a hard maximum number of steps (typically a small double-digit number, tuned per task) and stop when it is reached. Most runaway runs are a model repeating the same two calls. |
| 4 | - Track spend per run against a budget and abort when it is exceeded. Measure it in the currency you care about (tokens or money) and record it on the run so cost per task is a number you can see. |
| 5 | - Add a wall-clock timeout, since a slow tool can hold a run open long after the user stopped caring. |
| 6 | - Detect stalls: identical consecutive tool calls, no state change across steps, or repeated failures of the same tool. Stop and report rather than looping. |
| 7 | - Terminate explicitly and structurally: a final answer, a limit hit, or a failure, each with a reason the caller can branch on. A loop that ends by falling out of a condition tells you nothing about what happened. |
Design few, coarse tools with strict schemas and errors as data/src/agent/toolshighstrictEach tool completes a meaningful step, declares a strict validated schema, returns errors as structured results, and is safe to call twice.
| 1 | Tool design is the highest-leverage part of an agent, and it is the part most often copied from an internal API surface that was never meant for a model. |
| 2 | |
| 3 | - Prefer a small number of tools that each accomplish something a user would name, over many primitives the model must orchestrate. Every extra hop is another chance to choose wrong, and more tokens spent describing the surface. |
| 4 | - Declare a strict schema (required fields, enums, bounds) and validate arguments at the boundary. Return a clear validation error the model can correct rather than throwing an exception that kills the run. |
| 5 | - Return failures as structured results (`{ ok: false, code, message, hint }`), not as exceptions. A model can retry a described failure; it cannot recover from a stack trace. |
| 6 | - Make tools idempotent, or key them so a repeat is a no-op. A retried call must not send a second email or create a second record. |
| 7 | - Write the description for the model: what it does, when to use it, when not to, and what it returns. Keep outputs small and structured, and truncate large payloads with a pointer to fetch more rather than flooding the context. |
| 8 | - Never expose a generic "run this code" or "run this SQL" tool without a sandbox and read-only credentials. That is not a tool, it is remote execution. |
Separate read from write, and gate anything irreversible/src/agenthighstrictTools run with least privilege, destructive actions require explicit approval or a dry run, and every action is attributed and logged.
| 1 | An agent will eventually try the destructive path. The question is only whether your system lets it. |
| 2 | |
| 3 | - Classify every tool as read, reversible write, or irreversible, and give each class its own credentials. A read-only agent needs read-only keys; nothing needs a production admin role. |
| 4 | - Require human approval for irreversible or high-impact actions (money, deletions, external communication, production configuration), and present the exact action for confirmation rather than a summary of intent. |
| 5 | - Offer a dry run for anything bulk: show what would change, then apply on confirmation. This is also the cheapest way to debug agent behaviour. |
| 6 | - Act as the user, not as the system: authorize each tool call against the requesting user's permissions, so an agent cannot become a privilege escalation path. |
| 7 | - Log every tool call with its arguments, result, the run id, and the acting identity, and rate-limit and quota the agent per user and per tenant. If an agent can spend money or send messages, it needs the same abuse controls as a public endpoint. |
Curate the context and never trust what comes back/src/agenthighstrictSend the smallest sufficient context, summarize instead of accumulating, and treat tool output, documents, and web content as data rather than instructions.
| 1 | Most agent cost is paid on the input side, and most agent security incidents come from text the model was handed and treated as an instruction. |
| 2 | |
| 3 | - Send what the step needs, not everything available: relevant excerpts instead of whole files, a summary of earlier turns instead of the full transcript, and a scratchpad of decided facts rather than the entire history. |
| 4 | - Compact deliberately: when the context grows past a threshold, summarize what happened, keep the decisions and open questions, and drop the noise. Unbounded accumulation degrades both cost and accuracy. |
| 5 | - Mark every piece of retrieved content as untrusted data with a clear boundary, and instruct the model that content inside it is information, not commands. Fetched pages, ticket comments, file contents, and tool results are all attacker-influenced in some product. |
| 6 | - Never let retrieved text change the run's permissions, budget, or target. Those live in your code, not in the prompt, so no injected instruction can raise them. |
| 7 | - Keep the system prompt stable and versioned. A prompt edited by hand in production is an untracked deploy, and it invalidates every eval result you have. |
| 8 | |
| 9 | See /src/agent/tools for the tool contract and the rag-embeddings pattern for retrieval quality. |
Memories
2Loop architecture: state, checkpoints, and delegation/src/agentKeep run state outside the model, checkpoint each step so a run can resume, and delegate a bounded subtask to a subagent with its own budget.
| 1 | The loop is ordinary software. The parts that make it reliable are the parts that do not involve the model. |
| 2 | |
| 3 | - Keep authoritative state in your own store (goal, plan, completed steps, artifacts, budget spent), not only in the message history. The context is a view of state, not the state itself. |
| 4 | - Persist a checkpoint after each step so a crash, a rate limit, or a deploy can resume instead of restarting. Long-running agents need this the way any long job does. |
| 5 | - Stream progress to the user (the step, the tool being called, partial output). An agent that shows its work is debuggable and feels faster, and it lets a human interrupt before a wrong path gets expensive. |
| 6 | - Delegate a bounded subtask to a subagent when it needs its own long exploration, and give it its own step and cost budget plus a narrow tool set. Return a summary, not its whole transcript, so the parent context stays small. |
| 7 | - Make the whole run replayable: a stored transcript of prompts, tool calls, and results is what turns "the agent did something weird" into a fixable bug. |
| 8 | |
| 9 | See /src/agent for the loop bounds and the ai-sdk pattern for the client-side implementation details. |
You cannot improve what you do not trace/src/agentTrace every step with tokens, latency, and outcome, define task-level success metrics, and run an eval suite before any prompt, model, or tool change ships.
| 1 | Agent behaviour is not deterministic, so the only way to know whether a change helped is to measure it on a fixed set of tasks. |
| 2 | |
| 3 | - Trace each run as a tree of steps: prompt, model, tool calls with arguments and results, tokens in and out, latency, and the terminal reason. Tie it to a run id the user can quote. |
| 4 | - Define success at the task level, not the token level: did it complete the job, with how many steps, at what cost, and did a human have to intervene? Those four numbers are your dashboard. |
| 5 | - Keep an eval set of real tasks with known good outcomes, including the hard and adversarial ones, and run it before shipping a prompt change, a model change, a tool change, or a context change. Any of those four can regress the others. |
| 6 | - Watch the operational signals: step-limit hits, budget aborts, stalls, tool error rates, and approval rejection rate. A rising approval rejection rate means the agent is proposing the wrong actions, which is a prompt or tool problem, not a user problem. |
| 7 | - Version prompts and tool schemas alongside code, so a regression can be bisected like any other. |
| 8 | |
| 9 | See the llm-evals pattern for building the eval suite and the observability pattern for shipping these traces. |
Skills
1agent-loop-review/rootPre-merge review for an agent loop, a new tool, or a prompt change.
| 1 | --- |
| 2 | name: agent-loop-review |
| 3 | description: Review checklist for production LLM agents: loop bounds, tool contracts, privilege and approval gates, context and injection handling, and tracing and evals. Run before merging an agent, tool, or prompt change. |
| 4 | --- |
| 5 | |
| 6 | # Agent loop review |
| 7 | |
| 8 | ## Bounds |
| 9 | - [ ] Maximum step count, cost budget, and wall-clock timeout are all set. |
| 10 | - [ ] Stall detection stops repeated identical calls or no-progress steps. |
| 11 | - [ ] The run ends with a structured reason the caller can branch on. |
| 12 | |
| 13 | ## Tools |
| 14 | - [ ] Each tool completes a meaningful step; the surface is as small as the task allows. |
| 15 | - [ ] Schemas are strict and validated; invalid arguments return a correctable error. |
| 16 | - [ ] Failures return structured data, not thrown exceptions. |
| 17 | - [ ] Every tool is idempotent or keyed so a retry is a no-op. |
| 18 | - [ ] Outputs are small and truncated with a pointer, not dumped whole. |
| 19 | - [ ] No unsandboxed code or SQL execution tool. |
| 20 | |
| 21 | ## Privilege |
| 22 | - [ ] Read, reversible write, and irreversible tools have separate credentials. |
| 23 | - [ ] Irreversible and high-impact actions require explicit approval of the exact action. |
| 24 | - [ ] Bulk operations support a dry run. |
| 25 | - [ ] Tool calls are authorized as the requesting user, and logged with the run id. |
| 26 | - [ ] Per-user and per-tenant rate limits and quotas apply. |
| 27 | |
| 28 | ## Context |
| 29 | - [ ] Only the context the step needs is sent; history is summarized, not accumulated. |
| 30 | - [ ] Retrieved content is delimited and labelled untrusted; instructions inside it are ignored. |
| 31 | - [ ] Permissions, budgets, and targets live in code, not in the prompt. |
| 32 | - [ ] The system prompt is versioned in the repo. |
| 33 | |
| 34 | ## Evidence |
| 35 | - [ ] The run is fully traced (steps, tokens, latency, outcome) and replayable. |
| 36 | - [ ] The eval suite ran, and the result is recorded in the change. |
| 37 | - [ ] Operational alerts exist for limit hits, budget aborts, and tool error rates. |
Why this pattern
AI agents are shipped as an unbounded while loop with a dozen granular tools, full file contents pasted into context, write access to production, and no trace of what happened.
Built for Engineering teams putting LLM agents into a product or an internal workflow.
Keeps your assistant from:
- Running an agent loop with no step, cost, or wall-clock limit
- Exposing many granular tools instead of a few that complete a task
- Letting an agent take a destructive or irreversible action with no approval
- Treating tool output and fetched text as instructions rather than untrusted data
- License
- Apache-2.0
- Version
- 1.0.0
- Updated
- 2026-08-24