惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
Recent Commits to openclaw:main
Recent Commits to openclaw:main
H
Heimdal Security Blog
SecWiki News
SecWiki News
H
Hacker News: Front Page
N
News | PayPal Newsroom
L
LINUX DO - 最新话题
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
AI
AI
C
Cybersecurity and Infrastructure Security Agency CISA
Scott Helme
Scott Helme
PCI Perspectives
PCI Perspectives
S
Securelist
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cyberwarzone
Cyberwarzone
A
Arctic Wolf
Forbes - Security
Forbes - Security
T
Tor Project blog
Spread Privacy
Spread Privacy
WordPress大学
WordPress大学
I
Intezer
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Cisco Talos Blog
Cisco Talos Blog
Latest news
Latest news
博客园 - 司徒正美
W
WeLiveSecurity
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX
P
Palo Alto Networks Blog
Google DeepMind News
Google DeepMind News
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
V
Vulnerabilities – Threatpost
Jina AI
Jina AI
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
Simon Willison's Weblog
Simon Willison's Weblog
Project Zero
Project Zero
T
Threatpost
P
Privacy International News Feed
人人都是产品经理
人人都是产品经理
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
How to Build Production-Grade AI Agents
Mukesh Swamy · 2026-04-27 · via DEV Community

Most AI agent demos look impressive for five minutes and painful in the long run.

They can call a tool, stream a paragraph, maybe update a document, and then stop right where the real engineering work begins. Once you put an agent inside an actual product, you need much more than tool calling. You need resumable state, predictable execution, permission boundaries, observability, retries, approval flows, abort handling, model routing, and a UI that explains what the agent is doing without exposing raw implementation noise.

Here is what breaks when those pieces are missing:

  • Tool loops that never terminate
  • Writes that cannot be undone
  • Streams that say "thinking" but explain nothing useful
  • Background runs that fail with no resumable state
  • Product teams that cannot answer a simple question: what did the agent actually do?

When we launched agents at our product, we built them too much like model wrappers. Early demos looked good. Production exposed the gaps fast: brittle state, tool loops, weak recovery, and UI flows that held up only as long as users stayed on the happy path.

We have rebuilt the system several times since then. Each pass pushed us toward the same conclusion. An agent is not just a language model with tools bolted on. It is a workflow runtime that uses a language model as one part of the system. Model quality still matters, but reliability comes from the runtime around it.

This post is a condensed version of those rebuilds. It describes the architecture we are seeing that is working well, and the direction we believe product teams should take if they want agents that hold up in production.

The core principle: an agent is a runtime

An AI agent should not be a single function that sends messages to a model.

It should be a runtime with clear responsibilities:

  1. Maintain conversation and execution state.
  2. Convert product context into model-readable context.
  3. Stream model output and lifecycle events.
  4. Execute tools safely.
  5. Persist enough information to resume, inspect, undo, and debug runs.

A minimal production interface looks like this:

type AgentRuntimeInput = {
  conversationId?: string
  userId: string
  teamId: string
  modelKey: string
  systemPrompt: string
  messages: AgentMessage[]
  tools: AgentTool[]
  context: ProductContext
  signal?: AbortSignal
}

type AgentRuntimeEvent =
  | { type: "agent_start" }
  | { type: "turn_start"; turn: number }
  | { type: "message_delta"; text: string }
  | { type: "tool_start"; toolCallId: string; toolName: string; args: unknown }
  | { type: "tool_update"; toolCallId: string; result: unknown }
  | { type: "tool_end"; toolCallId: string; result: unknown; isError: boolean }
  | { type: "turn_end"; stopReason: string }
  | { type: "agent_end" }
  | { type: "error"; message: string }

Enter fullscreen mode Exit fullscreen mode

The important design choice is not the exact TypeScript. It is the event stream. Your UI, API route, background worker, and persistence layer should all consume the same stream of structured events.

That one decision pays off everywhere. The frontend gets stable states to render. The backend gets deterministic logs. Tests can assert event order. New tools can plug into the system without becoming one-off UI integrations.

The runtime loop is where reliability starts

Most agent failures are not prompt failures. They are runtime failures.

The loop itself is simple:

while (turn < maxTurns) {
  emit({ type: "turn_start", turn })

  const modelResult = await model.stream({
    systemPrompt,
    messages: transformContext(messages, context),
    tools: toolRegistry.toModelDefinitions(),
    signal,
    onTextDelta: (text) => emit({ type: "message_delta", text }),
  })

  if (modelResult.toolCalls.length === 0) {
    break
  }

  const toolResults = await executeToolBatch(modelResult.toolCalls)

  messages.push(toAssistantTurn(modelResult))
  messages.push(toToolResultTurn(toolResults))

  emit({ type: "turn_end", stopReason: modelResult.stopReason })
}

Enter fullscreen mode Exit fullscreen mode

What matters is everything around that loop:

  • Hard turn limits so broken tool plans do not run forever
  • Structured tool results so the model can reason over outcomes instead of vague strings
  • Abort propagation so "Stop" in the UI cancels both the model stream and long-running tools
  • Fallback finalization so the runtime can recover when a model completes tool work but never produces a user-facing answer
  • Retry policy for transient failures such as rate limits, timeouts, or unstable upstream APIs

If your agent can create drafts, mutate records, queue jobs, or call external systems, you do not have a chat loop anymore. You have a workflow engine with a language model inside it.

Tools need policy, not just schemas

In demos, tools are usually treated as plain functions with name, description, and parameters.

That is not enough in production. A tool is a product API with governance attached.

type AgentTool = {
  name: string
  label: string
  description: string
  parameters: JsonSchema

  executionMode?: "parallel" | "sequential"
  riskLevel: "read" | "write" | "external_side_effect"

  prepareArgs?: (args: unknown, context: AgentContext) => unknown

  beforeExecute?: (input: ToolExecutionInput) => Promise<{
    blocked?: boolean
    reason?: string
    requiresApproval?: boolean
  }>

  execute: (input: ToolExecutionInput) => Promise<ToolResult>

  afterExecute?: (input: ToolExecutionResult) => Promise<ToolExecutionResult>
}

Enter fullscreen mode Exit fullscreen mode

This structure gives the runtime enough information to behave like a product, not a demo.

Separate tool planning from tool authority

The model should decide intent. The product should decide authority.

A model can request:

{
  "name": "publish",
  "args": {
    "entityId": "article_123"
  }
}

Enter fullscreen mode Exit fullscreen mode

The runtime still decides whether that action is allowed.

That check can include:

  • User permissions
  • Team plan limits
  • Workspace settings
  • Approval requirements
  • Entity ownership
  • Risk level
  • Quiet hours
  • Rate limits
  • Whether the agent is in suggest mode or autopilot mode

This is the line that keeps agents safe: the model proposes actions; the runtime authorizes actions.

Decide what can run in parallel

Read-only tools often do not need to block each other. Loading relevant product knowledge and fetching recent GitHub commits can usually run in parallel.

Write paths should usually be sequential. Updating an article, publishing an announcement, capturing a screenshot, and moving a roadmap item should happen in an order you can explain and replay.

Treat undo as a runtime feature

If an agent can write, it should be able to undo.

const snapshot = await snapshotEntity(entity)

const result = await tool.execute({ args, entity, user })

await AiUndoEntry.create({
  conversationId,
  entityType,
  entityId,
  action: { toolName, args },
  snapshot,
})

Enter fullscreen mode Exit fullscreen mode

That turns "undo that" from a prompt gamble into a real product capability.

Context, model routing, and streaming should be first-class layers

Raw message history is not the same thing as model context.

Before every model call, the runtime should transform context into something the model can actually use:

async function transformContext(messages, productContext) {
  return [
    summarizeOldTurns(messages),
    injectCurrentEntity(productContext.entity),
    injectRelevantKnowledge(productContext.knowledge),
    injectRecentToolResults(messages),
    stripUiOnlyMessages(messages),
  ]
}

Enter fullscreen mode Exit fullscreen mode

This is where you prune old turns, inject the currently open entity, include relevant product knowledge, carry forward recent tool outputs, and strip out frontend-only noise.

Without this layer, prompts slowly become a dumping ground. With this layer, you can improve context quality without rewriting the runtime loop.

Route models through product policy

Production systems rarely stay on one model forever. You will want cheaper default models for common work, stronger reasoning models for complex tasks, and fallback behavior when an upstream provider is unavailable.

const MODEL_REGISTRY = {
  fast_default: {
    provider: "gemini",
    label: "Gemini Flash",
    maxOutputTokens: 65536,
    supportsThinking: true,
  },
  reasoning: {
    provider: "anthropic",
    label: "Claude Sonnet",
    maxOutputTokens: 64000,
    supportsTools: true,
  },
}

Enter fullscreen mode Exit fullscreen mode

Then resolve the actual model through policy:

const modelKey = resolveModelKey({
  requestedModelKey,
  agentType,
  teamPlan,
  teamConfig,
  fallbackModelKey,
})

Enter fullscreen mode Exit fullscreen mode

This keeps the UI simple while giving the backend room to evolve.

Stream product events, not just text

Streaming is part of the product interface. If the only thing your stream can send is a text delta, your UI has no structured way to explain progress.

Useful streams include lifecycle events like these:

emit({ type: "tool_start", toolName: "fetch_github_commits" })
emit({ type: "tool_end", toolName: "fetch_github_commits", result: { totalCount: 14 } })
emit({ type: "message_delta", text: "I found 14 commits..." })
emit({ type: "tasks_created", tasks })
emit({ type: "undo_entry", undoEntryId })

Enter fullscreen mode Exit fullscreen mode

The frontend can convert those into progress steps, generated content cards, inbox tasks, approval prompts, and undo buttons. The key is stability. Once the client starts parsing arbitrary ad hoc events, every new tool becomes a frontend rewrite.

Persistence is what makes agents inspectable and resumable

A production agent should persist much more than the final assistant message.

At minimum, persist:

  • Conversation metadata
  • User messages
  • Assistant messages
  • Tool calls
  • Tool results
  • Undo entries
  • Generated entities
  • Background task IDs
  • Run status
  • Error details
  • Timing information

This gives you the product behaviors users actually expect:

  • Reopen an old conversation
  • Inspect what the agent did
  • Resume failed work
  • Show generated drafts
  • Undo destructive changes
  • Audit scheduled or automated runs
  • Debug failures after deployment

For background agents, it is useful to persist runs separately from chat transcripts:

type AgentRun = {
  teamId: string
  agentType: "workspace" | "release" | "help_center" | "voc"
  triggerSource: "manual" | "schedule" | "webhook"
  status: "success" | "error" | "skipped"
  signalIds: string[]
  proposalsCreated: number
  reasoningTrace: unknown
  error?: string
  startedAt: Date
  finishedAt: Date
}

Enter fullscreen mode Exit fullscreen mode

Interactive chat and background automation should share the same runtime where possible. The trigger changes. The execution model should not.

Observability and validation are runtime features

Teams usually discover this too late: if you cannot see what the agent did and verify whether it did the right thing, you do not have a reliable system.

Observability starts with the same event stream and persistence model the rest of the runtime uses. Every meaningful step in a run should be traceable:

  • Which model was called
  • Which tool was requested
  • Which tool actually executed
  • Whether approval was required
  • How long each step took
  • What state changed
  • Why the run ended in success, error, or partial completion

That is what lets product teams answer the questions that show up in production: Why did this draft get created? Why did this run stop? Why did the agent skip publish and ask for approval instead?

Validation matters just as much. It should happen at multiple layers:

  • Input validation before a tool runs, so malformed arguments never reach your product APIs
  • Policy validation before a write happens, so permissions, workspace rules, and operating mode are enforced consistently
  • State validation before mutation, so the runtime checks that the target entity exists and is still in a valid state for the requested action
  • Outcome validation after execution, so the runtime verifies that the side effect actually happened and produced the expected result

Without that last layer, agents can fail in the most dangerous way: they appear successful while leaving the product in the wrong state.

This is also why observability and validation should live in the runtime, not inside individual prompts. Prompts can suggest what should happen. The runtime is what proves what actually happened.

Add explicit operating modes

Human approval should not be bolted on later. It should be part of the runtime contract from the start.

type AgentMode =
  | "off"
  | "suggest"
  | "auto_notify"
  | "auto_silent"

Enter fullscreen mode Exit fullscreen mode

In suggest mode, the agent creates proposals and a human approves them.

In auto_notify, the agent can execute low-risk approved classes of actions and notify the team.

In auto_silent, the agent can perform low-risk work without interrupting users.

The important point is that the same tool can behave differently depending on the mode. generate_article may create drafts automatically. publish may still require explicit approval unless the workspace configuration allows it.

Test the runtime, not just the prompt

The fastest way to build fragile agents is to test them only by talking to real models.

Use fake providers that return deterministic responses:

fakeModel.setResponses([
  assistantMessage([
    text("I'll fetch recent commits."),
    toolCall("fetch_github_commits", { repo: "acme/app", days: 7 }),
  ]),
  assistantMessage("I found 14 commits and created a draft changelog."),
])

Enter fullscreen mode Exit fullscreen mode

Then test the runtime itself:

  • Events are emitted in the correct order
  • Tool args are validated before execution
  • Tool calls and results are persisted
  • Tool errors are surfaced cleanly
  • Max turn limits are respected
  • Abort signals cancel the run
  • Undo entries are created for writes
  • Blocked tools are not executed
  • Saved context can resume a run

This is where reliability actually comes from. Prompt quality matters, but runtime tests are what keep the system stable when products, tools, and model providers change underneath you.

The architecture in one diagram

Production-grade AI agent runtime architecture

The exact boxes will vary by product. The shape should not.

If your architecture makes it easy to stop a run, inspect a run, resume a run, approve a write, and undo a mistake, you are moving in the right direction. If it only makes it easy to prompt a model and hope for the best, you are still in demo land.

The takeaway

The biggest mistake teams make is treating agents as prompts plus tools.

That works for demos. It does not work for products.

A production-grade agent is an event-driven runtime. The model plans. The runtime governs. Tools execute through product APIs. State is persisted. Risk is explicit. Users can stop, inspect, approve, and undo.

That architecture is more work up front. It gives you something far more valuable than a chatbot: an agent system that can safely operate inside your product.

Follow https://www.linkedin.com/in/mukeshswamy/ for similar content. Reach out via DM if you have questions.

References to go deeper

These are some of the systems that have shaped how we think about production-grade agent runtimes:

  • Mastra: resumable agent workflows and durable execution patterns
  • pi-mono: tool calling and state management
  • LangGraph: durable execution, streaming, and human-in-the-loop workflows
  • Pydantic AI: production-grade reliability patterns
  • OpenHands: local-first agent execution and cloud-scaled multi-agent systems