[{"data":1,"prerenderedAt":899},["ShallowReactive",2],{"blog-temporal-en":3},{"slug":4,"published":5,"minutes":6,"category":7,"tags":8,"keywords":14,"about":23,"sources":36,"cover":112,"og":113,"expertise":114,"locales":115,"lang":116,"title":119,"description":120,"coverAlt":121,"metaTitle":122,"takeaways":123,"faq":129,"toc":142,"blocks":170,"others":628},"temporal","2026-10-07",8,"agents",[9,10,11,12,13],"Durable execution","Workflow orchestration","Human in the loop","AI agents","Self-hosting",[15,16,17,18,19,20,21,22],"temporal workflow","temporal ai agents","durable execution for ai agents","temporal vs langgraph","temporal cloud pricing","temporal openai agents sdk","self-hosted temporal","temporal determinism rules",[24,27,30,33],{"name":25,"url":26},"Temporal","https:\u002F\u002Ftemporal.io",{"name":28,"url":29},"Workflow engine","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWorkflow_engine",{"name":31,"url":32},"Large language model","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLarge_language_model",{"name":34,"url":35},"Human-in-the-loop","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHuman-in-the-loop",[37,40,43,46,49,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100,103,106,109],{"title":38,"url":39},"Temporal Cloud pricing","https:\u002F\u002Ftemporal.io\u002Fpricing",{"title":41,"url":42},"Temporal Cloud pricing documentation","https:\u002F\u002Fdocs.temporal.io\u002Fcloud\u002Fpricing",{"title":44,"url":45},"OpenAI Agents SDK integration for Python","https:\u002F\u002Fdocs.temporal.io\u002Fdevelop\u002Fpython\u002Fintegrations\u002Fopenai-agents",{"title":47,"url":48},"Workflow definition and determinism","https:\u002F\u002Fdocs.temporal.io\u002Fworkflow-definition",{"title":50,"url":51},"Retry policies","https:\u002F\u002Fdocs.temporal.io\u002Fencyclopedia\u002Fretry-policies",{"title":53,"url":54},"Activity timeouts","https:\u002F\u002Fdocs.temporal.io\u002Fencyclopedia\u002Fdetecting-activity-failures",{"title":56,"url":57},"Cloud actions reference","https:\u002F\u002Fdocs.temporal.io\u002Fcloud\u002Factions",{"title":59,"url":60},"Event history limits","https:\u002F\u002Fdocs.temporal.io\u002Fworkflow-execution\u002Fevent",{"title":62,"url":63},"Message passing in Python: signals, queries and updates","https:\u002F\u002Fdocs.temporal.io\u002Fdevelop\u002Fpython\u002Fmessage-passing",{"title":65,"url":66},"Human-in-the-loop AI agent sample","https:\u002F\u002Fdocs.temporal.io\u002Fai\u002Fcookbook\u002Fhuman-in-the-loop-python",{"title":68,"url":69},"Cloud security model","https:\u002F\u002Fdocs.temporal.io\u002Fcloud\u002Fsecurity",{"title":71,"url":72},"Cloud service regions","https:\u002F\u002Fdocs.temporal.io\u002Fcloud\u002Fregions",{"title":74,"url":75},"Data processing agreement","https:\u002F\u002Ftemporal.io\u002Fdpa",{"title":77,"url":78},"Self-hosted deployment guide","https:\u002F\u002Fdocs.temporal.io\u002Fself-hosted-guide\u002Fdeployment",{"title":80,"url":81},"Self-hosted production checklist","https:\u002F\u002Fdocs.temporal.io\u002Fself-hosted-guide\u002Fproduction-checklist",{"title":83,"url":84},"Self-hosted visibility stores","https:\u002F\u002Fdocs.temporal.io\u002Fself-hosted-guide\u002Fvisibility",{"title":86,"url":87},"Temporal Server architecture","https:\u002F\u002Fdocs.temporal.io\u002Ftemporal-service\u002Ftemporal-server",{"title":89,"url":90},"Temporal server LICENSE file","https:\u002F\u002Fgithub.com\u002Ftemporalio\u002Ftemporal\u002Fblob\u002Fmain\u002FLICENSE",{"title":92,"url":93},"Temporal integrations index","https:\u002F\u002Fdocs.temporal.io\u002Fintegrations",{"title":95,"url":96},"LangGraph integration with Temporal","https:\u002F\u002Fdocs.temporal.io\u002Fdevelop\u002Fpython\u002Fintegrations\u002Flanggraph",{"title":98,"url":99},"LangGraph persistence","https:\u002F\u002Fdocs.langchain.com\u002Foss\u002Fpython\u002Flanggraph\u002Fpersistence",{"title":101,"url":102},"LangGraph interrupts","https:\u002F\u002Fdocs.langchain.com\u002Foss\u002Fpython\u002Flanggraph\u002Finterrupts",{"title":104,"url":105},"Self-hosted guide and development server","https:\u002F\u002Fdocs.temporal.io\u002Fself-hosted-guide",{"title":107,"url":108},"Python SDK reference: workflow.wait_condition","https:\u002F\u002Fpython.temporal.io\u002Ftemporalio.workflow._context.html",{"title":110,"url":111},"Python SDK reference: ApplicationError","https:\u002F\u002Fpython.temporal.io\u002Ftemporalio.exceptions.ApplicationError.html","\u002Fimages\u002Fblog\u002Ftemporal\u002Fcover.webp","\u002Fimages\u002Fblog\u002Ftemporal\u002Fog.jpg","ai-engineer",[116,117,118],"en","de","hu","Temporal review: durable agents that survive crashes and wait for people","Temporal runs agent loops as durable workflows, so retries, approvals and timers survive crashes. Costs, data residency, determinism rules and when to skip it.","Four stacked plates in a column on a slim pillar, with a gate and one figure.","Temporal review: durable agents that wait · Balázs Csorba",[124,125,126,127,128],"Temporal fits agent runs that last minutes to days, touch several systems and wait for a person. It is overkill for a chat reply that finishes in seconds.","The server is MIT-licensed. Temporal Cloud is pay-as-you-go from $0 a month, with Actions at $50 per million for the first 5 million, and the Business plan starts at $500 a month.","Workflow code must be deterministic. Model calls and tools belong in activities, and changing running workflow code needs versioning.","Activities retry without a limit by default, so every model activity needs a retry policy and a list of error types that must never be retried.","Cloud namespaces can run in EU regions such as Frankfurt and Ireland, under a data processing agreement with standard contractual clauses. Self-hosting moves that question to your own hosting.",[130,133,136,139],{"q":131,"a":132},"Is Temporal free to self-host?","The server is MIT-licensed, and Temporal's pricing page says the platform can run on your own infrastructure at no cost from Temporal. The database, the search store, the machines and the people who run them are still yours to pay for.",{"q":134,"a":135},"What does one agent run cost on Temporal Cloud?","A run with one start, twelve activity starts, two retries, an update, a signal and a timer is about 18 Actions. At $50 per million that is under a tenth of a cent in Actions, before storage and the 10 percent support charge.",{"q":137,"a":138},"Does a crash repeat my model calls?","Completed ones, no. Temporal replays the workflow from its recorded history and skips activities that already finished. An activity that was running when its worker died is retried once its start-to-close timeout expires, which is why activity code must be idempotent.",{"q":140,"a":141},"Temporal or LangGraph?","LangGraph is less to run when the agent is one graph in one Python process and a PostgreSQL checkpointer is enough. Temporal fits runs that last days, span several services or need retries and timers recorded by the platform. The two can also combine, because LangGraph can run inside a Temporal workflow, which is in public preview.",[143,146,149,152,155,158,161,164,167],{"id":144,"title":145},"what-it-is","What it is",{"id":147,"title":148},"how-it-works","How it works",{"id":150,"title":151},"getting-started","Getting started",{"id":153,"title":154},"retries-and-timeouts","Retries and timeouts",{"id":156,"title":157},"human-approval","Human approval with signals",{"id":159,"title":160},"cost-and-deployment","Cost and deployment",{"id":162,"title":163},"where-it-falls-short","Where it falls short",{"id":165,"title":166},"verdict","Verdict",{"id":168,"title":169},"sources","Sources",[171,175,178,181,205,206,217,223,234,235,246,248,266,267,270,287,289,308,311,312,323,325,345,346,349,404,407,410,436,442,448,449,487,488,491,512,515,540,549,550],{"type":172,"content":173},"paragraph",[174],"Temporal is an open-source durable execution platform. You write the agent as ordinary code, and the platform records every step, so a run survives crashes, deploys and days of waiting. My verdict up front: it suits agent runs that last minutes to days, touch several systems and need a person to approve a step. It is overkill for a chat reply that finishes in two seconds.",{"type":172,"content":176},[177],"It competes with two simpler things most teams already run: a graph checkpointer such as LangGraph's, and a job queue with a state table. Those are the right answer until a process dies halfway through a twelve-step run and the run has to resume where it stopped. Skip Temporal if nobody will own its workflow code or, when you self-host, its cluster.",{"type":179,"level":180,"id":144,"text":145},"heading",2,{"type":182,"ordered":183,"items":184},"list",false,[185,195,200],[186,190,194],{"tag":187,"children":188},"strong",[189],"One command to try it. ",{"tag":191,"children":192},"code",[193],"temporal server start-dev"," runs the service and the web UI on a laptop, with no external dependencies.",[196,199],{"tag":187,"children":197},[198],"Two ways to run it. ","Self-host the server, or use Temporal Cloud, whose regions include AWS Frankfurt and Ireland. The server is MIT-licensed.",[201,204],{"tag":187,"children":202},[203],"Ordinary code. ","Workflows and activities are plain functions in Go, Java, Python, TypeScript, .NET, Ruby or PHP, depending on the SDK.",{"type":179,"level":180,"id":147,"text":148},{"type":172,"content":207},[208,209,212,213,216],"A ",{"tag":187,"children":210},[211],"workflow"," decides what happens next. An ",{"tag":187,"children":214},[215],"activity"," does the work: it calls a model, hits an API or writes a file. Temporal stores each decision and each activity result in the workflow's event history. After a crash, a worker replays the workflow code against that history, skips the finished activities and resumes at the first unfinished step. An agent maps onto that split cleanly: the loop, the tool choice and any handoffs live in the workflow, and every model or tool call is an activity.",{"type":218,"src":219,"alt":220,"wide":221,"caption":222},"image","\u002Fimages\u002Fblog\u002Ftemporal\u002Fdiagram-6.webp","How a durable agent run flows through Temporal A client starts the workflow and sends signals and updates to the Temporal Service, which stores the event history and timers. A worker polls the task queue, receives tasks from the service and returns results. On the worker, the workflow code runs the agent loop deterministically and hands each model call or tool call to an activity. The activities call the external LLM and tool APIs, and those calls are not replayed.",true,"The workflow decides, the activities do the I\u002FO, and the service keeps the history that makes a restart harmless.",{"type":172,"content":224},[225,226,229,230,233],"Replay is the constraint. Workflow code must make the same calls in the same order on every replay, so calling an API, reading the clock or drawing random numbers inside it breaks replay. Put that work in activities, or use ",{"tag":191,"children":227},[228],"workflow.now()"," and ",{"tag":191,"children":231},[232],"workflow.random()"," in Python. Changing a workflow with running executions needs versioning. Changing an activity's type or ID is not safe, but its inputs and timeouts can change.",{"type":179,"level":180,"id":150,"text":151},{"type":172,"content":236},[237,238,241,242,245],"The quickest start is the OpenAI Agents SDK integration, shipped as the ",{"tag":191,"children":239},[240],"temporalio-openai-agents"," package. You write the agent with the normal SDK inside a workflow, then attach ",{"tag":191,"children":243},[244],"OpenAIAgentsPlugin"," to the client and the worker. Each model call becomes an activity, so it retries durably and is not repeated during replay.",{"type":191,"code":247},"from datetime import timedelta\nfrom agents import Agent, Runner\nfrom temporalio import workflow\nfrom temporalio.client import Client\nfrom temporalio.openai_agents import ModelActivityParameters, OpenAIAgentsPlugin\n\n\n@workflow.defn\nclass HelloWorldAgent:\n    @workflow.run\n    async def run(self, prompt: str) -> str:\n        agent = Agent(name='Assistant', instructions='You only respond in haikus.')\n        result = await Runner.run(agent, input=prompt)\n        return result.final_output\n\n\n# worker.py: the plugin sets the timeout for each model activity\nclient = await Client.connect(\n    'localhost:7233',\n    plugins=[\n        OpenAIAgentsPlugin(\n            model_params=ModelActivityParameters(\n                start_to_close_timeout=timedelta(seconds=30)\n            )\n        ),\n    ],\n)\n\n# starter.py: the same plugin, so payloads are converted the same way\nclient = await Client.connect('localhost:7233', plugins=[OpenAIAgentsPlugin()])\nresult = await client.execute_workflow(\n    HelloWorldAgent.run,\n    'Tell me about recursion in programming.',\n    id='my-workflow-id',\n    task_queue='openai-agents-basic-task-queue',\n)",{"type":172,"content":249},[250,253,254,257,258,261,262,265],{"tag":191,"children":251},[252],"ModelActivityParameters"," sets how model activities are scheduled, and its ",{"tag":191,"children":255},[256],"start_to_close_timeout"," defaults to 60 seconds. For tools, ",{"tag":191,"children":259},[260],"activity_as_tool()"," runs I\u002FO as an activity, while a plain ",{"tag":191,"children":263},[264],"@function_tool"," runs inside the workflow and must be deterministic. Integrations also exist for Google ADK, Pydantic AI, Mastra and the Vercel AI SDK. The LangGraph integration is in public preview.",{"type":179,"level":180,"id":153,"text":154},{"type":172,"content":268},[269],"Retries are where durable execution earns its keep, and where the defaults bite. A failed activity is retried with exponential backoff, starting at one second and capped at 100 seconds between attempts, with no limit on attempts. A payment capture wants that. A request that can never succeed, such as a lookup for an order that does not exist, should not be retried at all. Three settings decide the behaviour:",{"type":182,"ordered":183,"items":271},[272,277,282],[273,276],{"tag":187,"children":274},[275],"Start-to-close"," bounds one attempt. It has no default, and Temporal strongly recommends setting it.",[278,281],{"tag":187,"children":279},[280],"Schedule-to-close"," bounds the whole activity, retries included, so it caps how long one model step may run in total.",[283,286],{"tag":187,"children":284},[285],"Retry policy"," sets the attempt limit and the error types that must never be retried.",{"type":191,"code":288},"import httpx\nfrom datetime import timedelta\nfrom temporalio import activity\nfrom temporalio.common import RetryPolicy\nfrom temporalio.exceptions import ApplicationError\nfrom temporalio.openai_agents import ModelActivityParameters\n\nmodel_params = ModelActivityParameters(\n    start_to_close_timeout=timedelta(seconds=60),\n    schedule_to_close_timeout=timedelta(minutes=5),\n    retry_policy=RetryPolicy(maximum_attempts=5),\n)\n\n\n@activity.defn\nasync def lookup_order(order_id: str) -> dict:\n    async with httpx.AsyncClient() as client:\n        response = await client.get(f'https:\u002F\u002Fshop.example.com\u002Fapi\u002Forders\u002F{order_id}')\n    if response.status_code == 404:\n        # Retrying cannot make a missing order appear.\n        raise ApplicationError('Order not found', type='OrderNotFound', non_retryable=True)\n    response.raise_for_status()\n    return response.json()",{"type":290,"variant":291,"title":292,"body":293},"callout","warn","Every retry is a second model call",[294],[295,296,299,300,303,304,307],"A retry sends the request again, and every attempt counts another Action. Set ",{"tag":191,"children":297},[298],"maximum_attempts"," on every model activity, and raise ",{"tag":191,"children":301},[302],"ApplicationError"," with ",{"tag":191,"children":305},[306],"non_retryable=True"," for requests that cannot succeed.",{"type":172,"content":309},[310],"Activity code also has to be idempotent, because Temporal expects activities to re-execute after a failure. A tool that sends an email needs an idempotency key that the receiving system honours.",{"type":179,"level":180,"id":156,"text":157},{"type":172,"content":313},[314,315,318,319,322],"This is where Temporal stops being a retry library. A ",{"tag":187,"children":316},[317],"signal"," is an asynchronous message to a running workflow. Temporal's human-in-the-loop sample stores the decision in a signal handler and waits for it with ",{"tag":191,"children":320},[321],"workflow.wait_condition",". While it waits, the state lives in the event history and timers survive restarts. The sample's default timeout is five minutes, which suits a test. For an approval queue I would use days.",{"type":191,"code":324},"import asyncio\nfrom datetime import timedelta\nfrom typing import Optional\nfrom temporalio import workflow\n\n\n@workflow.defn\nclass ApprovalWorkflow:\n    def __init__(self) -> None:\n        self.decision: Optional[str] = None\n\n    @workflow.signal\n    async def approval_decision(self, decision: str) -> None:\n        self.decision = decision\n\n    @workflow.run\n    async def run(self, request: str) -> str:\n        # propose_action and execute_action are activities defined elsewhere\n        proposal = await workflow.execute_activity(\n            propose_action, request, start_to_close_timeout=timedelta(seconds=60)\n        )\n        try:\n            await workflow.wait_condition(\n                lambda: self.decision is not None,\n                timeout=timedelta(days=3),\n            )\n        except asyncio.TimeoutError:\n            return 'no decision within three days'\n        if self.decision != 'approve':\n            return 'rejected'\n        return await workflow.execute_activity(\n            execute_action, proposal, start_to_close_timeout=timedelta(seconds=60)\n        )",{"type":172,"content":326},[208,327,330,331,334,335,338,339,344],{"tag":187,"children":328},[329],"query"," reads state without changing it. An ",{"tag":187,"children":332},[333],"update"," is a request the caller waits on, and a validator can reject it before it is written to history. A rejected update still counts as an Action. Long sessions hit hard limits: an execution is terminated past 51,200 events, 2,000 updates or 10,000 signals, so chat-style workflows need Continue-As-New. ",{"tag":191,"children":336},[337],"workflow.info().is_continue_as_new_suggested()"," reports when the server suggests it. Where approval gates belong is a design question, which I cover in ",{"tag":340,"to":341,"children":342},"link","\u002Fblog\u002Fhuman-in-the-loop-ai-agents",[343],"Human in the loop for AI agents",".",{"type":179,"level":180,"id":159,"text":160},{"type":172,"content":347},[348],"Self-hosting carries no licence fee. Temporal Cloud is pay-as-you-go with no minimum spend, and new accounts get $150 of credit for 90 days. The table shows list prices as of October 2026.",{"type":350,"head":351,"rows":360},"table",[352,354,356,358],[353],"Option",[355],"Price",[357],"Included",[359],"What changes",[361,370,379,388,397],[362,364,366,368],[363],"Self-hosted",[365],"Free, MIT",[367],"Nothing from Temporal",[369],"You run the services, database, search store and upgrades",[371,373,375,377],[372],"Cloud pay-as-you-go",[374],"$0 base plus 10% support",[376],"Nothing",[378],"Actions at $50 per million for the first 5 million a month",[380,382,384,386],[381],"Cloud Business",[383],"Greater of $500 a month or 10% of usage",[385],"2.5M Actions, 2.5 GB active, 100 GB retained",[387],"SAML included, SCIM $500 a month extra",[389,391,393,395],[390],"Cloud Enterprise",[392],"Annual, contact sales",[394],"10M Actions, 10 GB active, 400 GB retained",[396],"SCIM included, P0 response under 30 minutes",[398,400,401,402],[399],"Cloud Mission Critical",[392],[394],[403],"Dedicated platform architect, P0 response under 15 minutes",{"type":172,"content":405},[406],"Usage rules move the bill more than the headline. Actions count every activity start and retry, and every signal, timer, update, query and workflow start. My example run is 18 Actions, so 100,000 such runs come to about $90 in Actions before storage and support. One GB of active storage held for a month costs about $31, and one GB of retained storage about 78 cents. With Fairness enabled, each hour's Actions rise by 10 percent.",{"type":172,"content":408},[409],"Business pays off through its support, SCIM and commitment discounts more than through its Actions. The $500 minimum includes 2.5 million Actions, which covers more than 130,000 runs like my example.",{"type":172,"content":411},[412,415,416,419,420,423,424,427,428,431,432,344],{"tag":187,"children":413},[414],"Where the data goes. ","A namespace is created in one region. The regions list includes AWS Frankfurt (",{"tag":191,"children":417},[418],"eu-central-1","), Ireland (",{"tag":191,"children":421},[422],"eu-west-1",") and London (",{"tag":191,"children":425},[426],"eu-west-2","), plus GCP Frankfurt (",{"tag":191,"children":429},[430],"europe-west3","). Payloads can be encrypted on your workers with the Data Converter before they leave, and a Codec Server lets your team read histories in the web UI without sharing keys. Retained history is kept for up to 90 days in Cloud, so longer retention means exporting. For the wider questions, see ",{"tag":340,"to":433,"children":434},"\u002Fblog\u002Fgdpr-llm-api-eu-data-residency",[435],"GDPR LLM data residency",{"type":172,"content":437},[438,441],{"tag":187,"children":439},[440],"The data processing agreement. ","Temporal's agreement, effective 10 October 2024, includes standard contractual clauses and a UK addendum. Its subprocessor list names AWS for infrastructure, Google Cloud for namespaces in GCP regions, and Datastax, Auth0, Elastic and WorkOS for specific services. You may object to a new subprocessor within 15 days of publication. Backups are kept for 30 days, and customer data is deleted on termination. Temporal says it is SOC 2 Type 2 certified and compliant with GDPR and HIPAA. Treat this as the start of your review, not as legal advice.",{"type":172,"content":443},[444,447],{"tag":187,"children":445},[446],"Self-hosting. ","That moves those questions to your own hosting provider, and you carry the database, the search store, backups and upgrades. The server has four services that scale independently: frontend, history, matching and worker. Elasticsearch or OpenSearch is recommended once you run more than a few executions, and the Docker Compose sample runs PostgreSQL with Elasticsearch. Temporal recommends upgrading one minor version at a time, and releases can arrive every two weeks. The shard count is fixed at build time, and there is no RBAC or audit logging out of the box. The vendor's checklist calls staffing a significant cost. I have not priced hardware, because it depends on shard count and load.",{"type":179,"level":180,"id":162,"text":163},{"type":182,"ordered":183,"items":450},[451,456,461,466,471],[452,455],{"tag":187,"children":453},[454],"Determinism is a habit. ","Editing code under running executions can break replay, and versioning leaves old code paths to maintain.",[457,460],{"tag":187,"children":458},[459],"Hard history ceilings. ","Executions terminate past 51,200 events, 2,000 updates or 10,000 signals, so long sessions need Continue-As-New from the start.",[462,465],{"tag":187,"children":463},[464],"Retries are a budget. ","The unlimited default suits infrastructure and suits model calls badly.",[467,470],{"tag":187,"children":468},[469],"Preview parts. ","The OpenTelemetry and LangGraph integrations are in public preview, sandbox support is pre-release and streaming is experimental.",[472,475,476,479,480,229,483,486],{"tag":187,"children":473},[474],"Not everything is durable. ","MCP servers run outside the workflow, and each MCP call runs as an activity. ",{"tag":191,"children":477},[478],"LocalShellTool",", ",{"tag":191,"children":481},[482],"ComputerTool",{"tag":191,"children":484},[485],"SQLiteSession"," are not supported.",{"type":179,"level":180,"id":165,"text":166},{"type":172,"content":489},[490],"Temporal is the right default for long-running agents that touch several systems and wait for people, provided someone will own the workflow code and, if you self-host, the cluster. It is the wrong default for one model call behind an HTTP request.",{"type":182,"ordered":221,"items":492},[493,498,502,507],[494,497],{"tag":187,"children":495},[496],"Adopt it if ","a run lasts hours or days, and a restart must not repeat a payment, an email or a model call.",[499,501],{"tag":187,"children":500},[496],"a person approves steps that may come days later, and the wait must survive restarts.",[503,506],{"tag":187,"children":504},[505],"Skip it if ","the agent answers in seconds. A timeout and a retry around the model call are enough.",[508,511],{"tag":187,"children":509},[510],"Self-host it only if ","someone will run the cluster through frequent upgrades. Otherwise use Temporal Cloud.",{"type":172,"content":513},[514],"Three alternatives cover most cases where Temporal is overkill:",{"type":182,"ordered":183,"items":516},[517,526,531],[518,521,525],{"tag":187,"children":519},[520],"LangGraph checkpoints ",{"tag":340,"to":522,"children":523},"\u002Fblog\u002Flanggraph",[524],"LangGraph"," when the agent is one Python graph, the state is small and PostgreSQL is already there. Its interrupts pause a graph for human approval.",[527,530],{"tag":187,"children":528},[529],"A job queue with a state table ","when the pipeline is a fixed sequence of idempotent steps. You build the retries and timers yourself, which is fine for five steps and tedious for fifty.",[532,535,539],{"tag":187,"children":533},[534],"The OpenAI Agents SDK alone ",{"tag":340,"to":536,"children":537},"\u002Fblog\u002Fopenai-agents-sdk",[538],"OpenAI Agents SDK"," when each run is short, stays in one process and never needs to survive a restart.",{"type":290,"variant":541,"title":542,"body":543},"tip","Start small",[544],[545,546,548],"Begin with ",{"tag":191,"children":547},[193]," and the $150 of Cloud credit. Move to a cluster only when a residency rule or measured volume makes the case.",{"type":179,"level":180,"id":168,"text":169},{"type":182,"ordered":183,"items":551},[552,556,559,562,565,568,571,574,577,580,583,586,589,592,595,598,601,604,607,610,613,616,619,622,625],[553],{"tag":554,"href":39,"children":555},"a",[38],[557],{"tag":554,"href":42,"children":558},[41],[560],{"tag":554,"href":45,"children":561},[44],[563],{"tag":554,"href":48,"children":564},[47],[566],{"tag":554,"href":51,"children":567},[50],[569],{"tag":554,"href":54,"children":570},[53],[572],{"tag":554,"href":57,"children":573},[56],[575],{"tag":554,"href":60,"children":576},[59],[578],{"tag":554,"href":63,"children":579},[62],[581],{"tag":554,"href":66,"children":582},[65],[584],{"tag":554,"href":69,"children":585},[68],[587],{"tag":554,"href":72,"children":588},[71],[590],{"tag":554,"href":75,"children":591},[74],[593],{"tag":554,"href":78,"children":594},[77],[596],{"tag":554,"href":81,"children":597},[80],[599],{"tag":554,"href":84,"children":600},[83],[602],{"tag":554,"href":87,"children":603},[86],[605],{"tag":554,"href":90,"children":606},[89],[608],{"tag":554,"href":93,"children":609},[92],[611],{"tag":554,"href":96,"children":612},[95],[614],{"tag":554,"href":99,"children":615},[98],[617],{"tag":554,"href":102,"children":618},[101],[620],{"tag":554,"href":105,"children":621},[104],[623],{"tag":554,"href":108,"children":624},[107],[626],{"tag":554,"href":111,"children":627},[110],[629,687,760,830],{"slug":630,"published":631,"minutes":632,"category":7,"tags":633,"keywords":638,"about":649,"sources":659,"cover":681,"og":682,"expertise":114,"locales":683,"lang":116,"title":684,"description":685,"coverAlt":686},"agent-tool-design-descriptions-errors","2026-10-17",11,[12,634,635,636,637],"Tool use","Function calling","MCP","Agent design",[639,640,641,642,643,644,645,646,647,648],"agent tool design","writing tool descriptions for llm","function calling best practices","tool use error handling","mcp tool design","tool calling is_error","how many tools should an agent have","tool search defer_loading","agent computer interface","llm tool schema design",[650,653,656],{"name":651,"url":652},"Intelligent agent","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FIntelligent_agent",{"name":654,"url":655},"Model Context Protocol","https:\u002F\u002Fmodelcontextprotocol.io\u002F",{"name":657,"url":658},"Poka-yoke","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPoka-yoke",[660,663,666,669,672,675,678],{"title":661,"url":662},"Anthropic Engineering: Writing effective tools for agents, with agents (Sep 2025)","https:\u002F\u002Fwww.anthropic.com\u002Fengineering\u002Fwriting-tools-for-agents",{"title":664,"url":665},"Anthropic Engineering: Building effective agents (Dec 2024)","https:\u002F\u002Fwww.anthropic.com\u002Fengineering\u002Fbuilding-effective-agents",{"title":667,"url":668},"Claude Platform Docs: Define tools","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fagents-and-tools\u002Ftool-use\u002Fdefine-tools",{"title":670,"url":671},"Claude Platform Docs: Handle tool calls","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fagents-and-tools\u002Ftool-use\u002Fhandle-tool-calls",{"title":673,"url":674},"Claude Platform Docs: Tool search tool","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fagents-and-tools\u002Ftool-use\u002Ftool-search-tool",{"title":676,"url":677},"Model Context Protocol specification 2025-11-25: Tools","https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2025-11-25\u002Fserver\u002Ftools",{"title":679,"url":680},"OpenAI API Docs: Function calling","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Ffunction-calling","\u002Fimages\u002Fblog\u002Fagent-tool-design-descriptions-errors\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fagent-tool-design-descriptions-errors\u002Fog.jpg",[116,117,118],"Designing tools for AI agents: names, descriptions, schemas and error messages","How to design agent tools that get picked and called correctly: task-shaped tools, descriptions, schemas, compact responses and errors a model can act on.","Three rectangular slots in a base, with a block of matching width lined up over the middle slot and two wrong-width blocks beside it.",{"slug":688,"published":631,"minutes":632,"category":7,"tags":689,"keywords":695,"about":708,"sources":718,"cover":754,"og":755,"expertise":114,"locales":756,"lang":116,"title":757,"description":758,"coverAlt":759},"coding-agents-legacy-codebase-migration",[690,691,692,693,694],"Legacy migration","Coding agents","Strangler fig","Testing","Code review",[696,697,698,699,700,701,702,703,704,705,706,707],"legacy code migration ai","coding agent legacy codebase","strangler fig pattern ai","characterization tests legacy code","ai code migration review","agent assisted refactoring","legacy modernization coding agent","differential testing migration","shadow traffic migration","ai code review gate","test harness before migration","llm code migration",[709,712,715],{"name":710,"url":711},"Legacy code","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLegacy_code",{"name":713,"url":714},"Characterization test","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCharacterization_test",{"name":716,"url":717},"Strangler fig pattern","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FStrangler_fig_pattern",[719,722,724,727,730,733,736,739,742,745,748,751],{"title":720,"url":721},"Martin Fowler: Strangler Fig (2024)","https:\u002F\u002Fmartinfowler.com\u002Fbliki\u002FStranglerFigApplication.html",{"title":723,"url":714},"Wikipedia: Characterization test",{"title":725,"url":726},"Google Research: Accelerating code migrations with AI (2024)","https:\u002F\u002Fresearch.google\u002Fblog\u002Faccelerating-code-migrations-with-ai\u002F",{"title":728,"url":729},"Ziftci et al.: Migrating Code At Scale With LLMs At Google (arXiv 2504.09691)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2504.09691",{"title":731,"url":732},"Anthropic: Effective harnesses for long-running agents (2025)","https:\u002F\u002Fwww.anthropic.com\u002Fengineering\u002Feffective-harnesses-for-long-running-agents",{"title":734,"url":735},"Anthropic: Redesigning source control at Anthropic (2026)","https:\u002F\u002Fwww.anthropic.com\u002Fengineering\u002Fredesigning-source-control",{"title":737,"url":738},"METR: Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity","https:\u002F\u002Fmetr.org\u002Fblog\u002F2025-07-10-early-2025-ai-experienced-os-dev-study\u002F",{"title":740,"url":741},"Chand et al.: Why Industry Migrates and When It Trusts LLMs (ESEM 2026)","https:\u002F\u002Fdrops.dagstuhl.de\u002Fentities\u002Fdocument\u002F10.4230\u002FLIPIcs.ESEM.2026.85",{"title":743,"url":744},"Li et al.: Environment-in-the-Loop: Rethinking Code Migration with LLM-based Agents (arXiv 2602.09944)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2602.09944",{"title":746,"url":747},"AWS: Amazon Q Developer just reached a $260 million dollar milestone (2024)","https:\u002F\u002Faws.amazon.com\u002Fblogs\u002Fdevops\u002Famazon-q-developer-just-reached-a-260-million-dollar-milestone\u002F",{"title":749,"url":750},"OpenAI: Why SWE-bench Verified no longer measures frontier coding capabilities (2026)","https:\u002F\u002Fopenai.com\u002Findex\u002Fwhy-we-no-longer-evaluate-swe-bench-verified\u002F",{"title":752,"url":753},"GitHub Docs: About GitHub Copilot cloud agent","https:\u002F\u002Fdocs.github.com\u002Fen\u002Fcopilot\u002Fconcepts\u002Fagents\u002Fcoding-agent\u002Fabout-coding-agent","\u002Fimages\u002Fblog\u002Fcoding-agents-legacy-codebase-migration\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fcoding-agents-legacy-codebase-migration\u002Fog.jpg",[116,117,118],"Migrating a legacy codebase with coding agents: a strangler fig playbook","How to use coding agents on a legacy migration: characterization tests first, one seam per task, review gates and differential verification.","A stack of slabs with the top two replaced by fresh ones beside a seam and a check.",{"slug":761,"published":631,"minutes":762,"category":7,"tags":763,"keywords":767,"about":779,"sources":789,"cover":824,"og":825,"expertise":114,"locales":826,"lang":116,"title":827,"description":828,"coverAlt":829},"background-agents-async-pr-workflow",12,[691,764,765,694,766],"Pull requests","CI","Automation",[768,769,770,771,772,773,774,775,776,777,778],"background coding agent","async coding agent","cloud coding agent pull request","copilot coding agent limits","codex cloud tasks","claude code cloud sessions","jules coding agent limits","agent pull request review","coding agent sandbox","agent CI gating","cost per merged pull request",[780,783,786],{"name":781,"url":782},"Software agent","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSoftware_agent",{"name":784,"url":785},"Pull request","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FDistributed_version_control",{"name":787,"url":788},"Continuous integration","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FContinuous_integration",[790,791,794,797,800,803,806,809,812,815,818,821],{"title":752,"url":753},{"title":792,"url":793},"GitHub Docs: Risks and mitigations for Copilot cloud agent","https:\u002F\u002Fdocs.github.com\u002Fen\u002Fcopilot\u002Fconcepts\u002Fagents\u002Fcloud-agent\u002Frisks-and-mitigations",{"title":795,"url":796},"OpenAI Developers: Codex cloud environments","https:\u002F\u002Fdevelopers.openai.com\u002Fcodex\u002Fcloud\u002Fenvironments",{"title":798,"url":799},"Anthropic: Use Claude Code in the cloud","https:\u002F\u002Fcode.claude.com\u002Fdocs\u002Fen\u002Fclaude-code-on-the-web",{"title":801,"url":802},"Google Jules: Limits and plans","https:\u002F\u002Fjules.google\u002Fdocs\u002Fusage-limits\u002F",{"title":804,"url":805},"Google Jules: Getting started","https:\u002F\u002Fjules.google\u002Fdocs\u002F",{"title":807,"url":808},"GitHub Docs: About protected branches","https:\u002F\u002Fdocs.github.com\u002Fen\u002Frepositories\u002Fconfiguring-branches-and-merges-in-your-repository\u002Fmanaging-protected-branches\u002Fabout-protected-branches",{"title":810,"url":811},"GitHub Docs: Models and pricing for GitHub Copilot","https:\u002F\u002Fdocs.github.com\u002Fen\u002Fcopilot\u002Freference\u002Fcopilot-billing\u002Fmodels-and-pricing",{"title":813,"url":814},"OpenAI Developers: Codex pricing","https:\u002F\u002Fdevelopers.openai.com\u002Fcodex\u002Fpricing",{"title":816,"url":817},"Ehsani et al.: Where Do AI Coding Agents Fail? An Empirical Study of Failed Agentic Pull Requests in GitHub (MSR 2026, arXiv 2601.15195)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2601.15195",{"title":819,"url":820},"Peralta et al.: Why Are Agentic Pull Requests Merged or Rejected? An Empirical Study (MSR 2026, arXiv 2605.22534)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2605.22534",{"title":822,"url":823},"DORA: State of AI-assisted Software Development 2025","https:\u002F\u002Fdora.dev\u002Fdora-report-2025","\u002Fimages\u002Fblog\u002Fbackground-agents-async-pr-workflow\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fbackground-agents-async-pr-workflow\u002Fog.jpg",[116,117,118],"Background coding agents that open PRs: a practical async workflow","How async coding agents queue tasks, run in sandboxes, open draft PRs and pass CI. Provider limits, cost controls, review design and failure modes.","One card in a tray fanning out to five pads, all arrows leading to one page behind a gate.",{"slug":831,"published":832,"minutes":833,"category":7,"tags":834,"keywords":840,"about":852,"sources":860,"cover":893,"og":894,"expertise":114,"locales":895,"lang":116,"title":896,"description":897,"coverAlt":898},"context-rot-compaction-long-running-agents","2026-10-16",10,[835,836,837,838,839],"Context rot","Compaction","Context engineering","Long-running agents","Agent memory",[841,842,843,844,845,846,847,848,849,850,851],"context rot","context rot LLM","compaction AI agents","context engineering","long-running agents context window","Claude compaction API","context editing clear tool results","OpenAI responses compaction","lost in the middle LLM","agent context management","sub-agents context isolation",[853,856,859],{"name":854,"url":855},"Context window","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLarge_language_model#Context_window",{"name":857,"url":858},"Attention (machine learning)","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FAttention_(machine_learning)",{"name":651,"url":652},[861,864,867,870,873,875,878,881,884,887,890],{"title":862,"url":863},"Chroma: Context Rot: How Increasing Input Tokens Impacts LLM Performance (Jul 2025)","https:\u002F\u002Fresearch.trychroma.com\u002Fcontext-rot",{"title":865,"url":866},"Liu et al.: Lost in the Middle: How Language Models Use Long Contexts (2023)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2307.03172",{"title":868,"url":869},"Modarressi et al.: NoLiMa: Long-Context Evaluation Beyond Literal Matching (2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2502.05167",{"title":871,"url":872},"Anthropic: Effective context engineering for AI agents (Sep 2025)","https:\u002F\u002Fwww.anthropic.com\u002Fengineering\u002Feffective-context-engineering-for-ai-agents",{"title":874,"url":732},"Anthropic: Effective harnesses for long-running agents (Nov 2025)",{"title":876,"url":877},"Claude API docs: Compaction at a token threshold","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fcompaction-threshold",{"title":879,"url":880},"Claude API docs: Compaction on demand","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fcompaction-on-demand",{"title":882,"url":883},"Claude API docs: Context editing","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fcontext-editing",{"title":885,"url":886},"Claude API docs: Memory tool","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fagents-and-tools\u002Ftool-use\u002Fmemory-tool",{"title":888,"url":889},"OpenAI API docs: Compaction","https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Fcompaction",{"title":891,"url":892},"Cognition: Don't Build Multi-Agents","https:\u002F\u002Fcognition.ai\u002Fblog\u002Fdont-build-multi-agents","\u002Fimages\u002Fblog\u002Fcontext-rot-compaction-long-running-agents\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fcontext-rot-compaction-long-running-agents\u002Fog.jpg",[116,117,118],"Context rot in long-running agents: clearing, compaction, memory and sub-agents","Why LLM accuracy drops as context grows, and how clearing tool results, compaction, notes and sub-agents keep long-running agents on track.","A small square press squeezing a tall stack of sheets into a short one, two notes branching off.",1792261155579]