←新闻详情

Pydantic AI 官方文章更新于 10月12日 19:53

Pydantic AI Harness 推出 AWSLambdaDurability,让智能体在 AWS Lambda 上可持久运行

Durable Pydantic AI agents on AWS Lambda

AI 导读

Pydantic AI Harness 发布 AWSLambdaDurability 能力,把每次模型请求、函数工具调用、MCP 调用和动态工具集解析都记录为 AWS Lambda durable functions 的步骤,恢复执行时从存储结果中读取已完成步骤。使用时需在构建智能体时挂载该能力,并用 durable_agent_handler 改造处理函数,@durable_execution 必须位于最外层。步骤默认至少执行一次并带重试,副作用需保持幂等;改变步骤数量或顺序会使在途执行失效,需发布新版本并让旧版本执行完。

推荐理由

精选AI 评分 65

原文给出在 AWS Lambda 上让智能体运行可断点续跑的具体能力与配置约束,读者可据此判断长任务重试成本如何下降。

主题

标签

正文

当前显示原文,中文全文译文尚未就绪。

Picture this: an AI support agent spends fifteen minutes working on a ticket. It reads the order, calls the billing API, asks the model what to do next, calls another tool, and somewhere in the eleventh minute the Lambda invocation times out. Lambda retries it. The handler runs again from the first line, so the same model requests go out, the same tools run, the same tokens land on the same invoice, and the billing API issues a second refund for the ticket it already refunded. You now have spent double as many tokens, and have a duplicated refund.

This might sound like a bug, but it is not. A Lambda handler is stateless, and a retry has nothing to resume from because nothing recorded what the run had already finished.

AWS Lambda durable functions let you build reliable, long-running workflows on Lambda. A durable function can pause, wait for external events, retry failed operations, and resume where it left off, even if Lambda recycles the execution environment. Under the hood, durable functions are regular Lambda functions that use a checkpoint and replay mechanism to track progress. An execution can span up to a year, and a wait suspends it without compute charges for on-demand functions.

Pydantic AI Harness now ships AWSLambdaDurability, a capability that makes the run durable: every model request, function tool call, MCP call, and dynamic-toolset resolution is checkpointed as an AWS Lambda durable functions step. A resumed execution replays the handler from the top and serves completed steps from stored results.

#Getting started

The AWS Durable Execution SDK needs Python 3.11 or newer. logfire carries the instrumentation behind every trace in this post.

Building agents in production?

See what they're actually doing with Logfire — traces, evals, cost, and behavior in one view.

#An agent in a handler

Put an agent in a handler and deploy it. This is the honest starting point, and for a lookup that finishes in four seconds it is also the finishing point:

The ceiling is the retry. When the invocation source retries a failed handler, such as an asynchronous or event-source invocation after a timeout, throttling, or a transient network error, the whole run starts again, so you pay for the completed work as well as the failed step.

#Build a durable Lambda handler

Attach the capability when you build the agent, then adapt the handler body with durable_agent_handler:

Two decorators and one capability. @durable_execution has to be outermost, because its wrapper is what Lambda invokes, and reversing the order raises a UserError when the handler is defined. Underneath, durable_agent_handler hosts the async agent on a background event loop and services its steps on the Lambda handler thread, which is how a synchronous durable API and an async agent run end up in one continuous step sequence.

Deploy it with a durable configuration and invoke a published version, since in-flight executions are pinned to the version that started them:

create-function returns while Lambda may still be provisioning the function. The waiters confirm both State=Active and LastUpdateStatus=Successful, preventing publish-version from racing that work and failing with ResourceConflictException.

The role behind --role needs lambda:CheckpointDurableExecution and lambda:GetDurableExecutionState, which the AWS managed AWSLambdaBasicDurableExecutionRolePolicy carries. The console attaches them when it creates a durable function and the CLI does not, so a function deployed like this on an ordinary execution role fails at its first checkpoint.

The agent keeps the API it had before. Same Agent, same tools, same output_type if it has one, and the run now survives the invocation it started in.

Attaching the capability does not make a run durable by itself. Only a run entered through durable_agent_handler or run_durable is checkpointed, so await agent.run(...) in the handler body is the durable path. Drive the same agent from your own asyncio.run(...) somewhere else and you get a fully working, non-durable run with no warning at all. agent.run_sync(...) inside the handler body does not even get that far: the body is already on a running event loop, and run_sync cannot be called from one.

Step names use the agent's name, or AWSLambdaDurability(name=...) when the agent is unnamed, together with each toolset's id. The weather tool above is checkpointed as support__function_toolset__ .call_tool:get_weather, and a model request is support__model.request. Those names are what you read when a resumed execution does something surprising.

#Watching one across invocations

The two Logfire lines in the snippet are what make a durable run readable. logfire.instrument_pydantic_ai() puts every model request and tool call in the trace, and those are the same operations Lambda checkpoints under the step names above, so a step in the durable log has a span you can open and read the arguments of.

A run that resumes is not one trace, though. Each invocation traces itself, and the invocation that picks the run back up records only the steps that actually executed: the completed ones return their stored results instead of running, so they have nothing to report. Reading a resumed run means reading the invocations in order, and the short second trace is the good outcome. It is the work you did not pay for twice.

#Tune it when the run earns it

Checkpointing is per step, so the configuration is per tool. Metadata under the aws_lambda key sets that tool's retry_strategy, step_semantics, and serdes:

AWSLambdaDurability(step_config=...) sets the base for every step, and per-tool metadata overrides it key by key, so a tool that sets only step_semantics keeps the base retry strategy. At the other end, metadata={'aws_lambda': False} opts a tool out of checkpointing entirely and lets it run inline on every attempt, which is the right call for something cheap and side-effect-free. MCP tools cannot opt out, because they do I/O that must not re-run.

Two constraints:

Steps are at least once, and retried by default. A step is checkpointed after it runs, so an interruption between a tool's side effect and its checkpoint re-runs the tool on resume. The SDK's default policy allows six total attempts (the initial attempt plus five retries) with exponential backoff. Keep side effects idempotent. For the tool that genuinely must not repeat, AT_MOST_ONCE_PER_RETRY is only half the answer: it prevents re-execution within an attempt, and the retry policy still starts further attempts that do execute the body. Set both, pairing it with RetryPresets.none(). While you are there, turn off one of the two retry layers, because Pydantic AI and the provider clients have their own and stacking them multiplies attempts and mishandles Retry-After.

Changing the shape of the run breaks in-flight executions. Checkpoints are matched by the order operations are reached, so adding a tool, removing an MCP server, flipping an opt-out, adding an event_stream_handler, or changing the model all shift the sequence out from under an execution that started on the old code. Publish a new version and let the old one drain. This is the same discipline a schema migration asks for, applied to the shape of an agent.

#Which durable execution to reach for

Pydantic AI officially supports five durable execution solutions. Temporal and Restate put a server in front of your agent and provide durable orchestration. DBOS runs in-process as a library and checkpoints into a database you already have, and Prefect brings the transactional semantics of a workflow framework. Lambda durability is the one that adds no component at all: if the agent is already a function, durability is a capability, two decorators, and a flag on the deploy. The durable execution docs cover all five.

The AWS Lambda durability docs document every step name, the per-tool configuration, and the budgets, and the capability matrix tracks the rest of the shelf.

#Frequently asked questions

Does this work with any model provider, or only Amazon Bedrock?

Any provider Pydantic AI supports. The capability checkpoints the model request itself, not a particular client, and a model operation that does not use the agent's default model records its model id in the step name so a resumed execution maps each checkpoint back to the model it was recorded for. Bedrock appears in the examples because it is the provider most Lambda deployments reach for first.

What does checkpointing cost?

Steps consume a durable execution's operations and storage quotas. A turn consumes one model step plus one step per tool call. Large tool results consume the storage budget, so store references, not payloads, or use the FileSystem serdes to keep large values on Amazon S3 Files and checkpoint only a file pointer. You benefit because you do not pay for repeated model requests and repeated tool calls on every retry. Please see durable functions quotas.

Can tools still run in parallel?

Not inside a durable handler. A step's identity comes from the order steps are reached, so concurrently scheduled tool calls could claim each other's checkpoints on resume. The run is switched to sequential tool execution inside the handler and keeps its configured parallelism everywhere else.

What happens if I redeploy while executions are running?

They break, unless you version. A resumed execution matches checkpoints positionally, so any change to the number or order of steps invalidates executions started under the old code, and renaming the agent or a toolset id changes the recorded names too. Deploy under a new published version and let in-flight executions finish on the old one.

Can I stream tokens out of a durable execution?

Not to a caller. A durable execution returns a single value when it completes, so there is no channel to stream through while it runs. run_stream and iter still work inside the handler and are checkpointed normally, and an event_stream_handler gets you live model events inside the model step, with each agent-level event checkpointed in its own step.

来源

Pydantic AI 官方文章