Skip to content

Add Pydantic AI Durable Capability Example#552

Draft
nvasiu wants to merge 1 commit into
mainfrom
pydantic-ai-durable-capability
Draft

Add Pydantic AI Durable Capability Example#552
nvasiu wants to merge 1 commit into
mainfrom
pydantic-ai-durable-capability

Conversation

@nvasiu

@nvasiu nvasiu commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Pydantic AI Durable Agent

A Pydantic AI agent as a Lambda durable function. Each model request and tool
call is checkpointed as a durable step.

  • lambda_durability.py — the LambdaDurability capability.
  • pydantic_ai_agent.py — the durable handler and agent.
  • pydantic-ai-agent.zip — prebuilt deployment package (built for the Lambda
    python3.13 / x86_64 runtime).

Requires an execution role with durable execution and bedrock:InvokeModel
permissions, and Bedrock access for PYDANTIC_AI_MODEL
(default us.amazon.nova-micro-v1:0).

Deploy

aws lambda create-function \
  --function-name pydantic-ai-agent \
  --runtime python3.13 \
  --handler pydantic_ai_agent.handler \
  --role <ROLE_ARN> \
  --zip-file fileb://pydantic-ai-agent.zip \
  --timeout 300 --memory-size 1024 \
  --environment '{"Variables":{"PYDANTIC_AI_MODEL":"us.amazon.nova-micro-v1:0"}}' \
  --durable-config '{"ExecutionTimeout":3600,"RetentionPeriodInDays":7}' \
  --region us-east-1

aws lambda wait function-active --function-name pydantic-ai-agent --region us-east-1
aws lambda publish-version --function-name pydantic-ai-agent --region us-east-1

Invoke

aws lambda invoke \
  --function-name pydantic-ai-agent:1 \
  --invocation-type Event \
  --payload '{"prompt":"What is the weather in Vancouver?"}' \
  --region us-east-1 /dev/stdout

aws lambda get-durable-execution \
  --durable-execution-arn "<DurableExecutionArn>" --region us-east-1

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

# is not recorded as failed.
async def call_tool():
try:
return {"retry": False, "value": await handler(args)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return value from handler may not be serializable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep this demo simple, tool results are just assumed to be JSON serializable.

In the future we'll add a per-tool config to allow users to specify custom SerDes for each tool.

@nvasiu
nvasiu force-pushed the pydantic-ai-durable-capability branch from 3c5d118 to e8d8d74 Compare July 20, 2026 18:09

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this zip for?

rather than check in a zip to github, where it will increase the size of a git clone forever more, can we make this a script instead? A script to make the zip?


from __future__ import annotations

import asyncio

@yaythomas yaythomas Jul 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ruff F401 — unused import asyncio at test/pydantic_ai_agent/test_pydantic_ai_agent.py:5. Auto-fixable.

)
def test_pydantic_ai_agent_runs_in_cloud(durable_runner):
if durable_runner.mode != "cloud":
pytest.skip("Pydantic AI Bedrock example only runs in cloud mode")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the durable_runner fixture calls pytest.fail("handler is required for local mode tests"), so strictly speaking this is dead code, I think?

assert deserialize_operation_payload(result.result)
operation_names = {operation.name for operation in result.operations}
assert any(name and name.startswith("model.request") for name in operation_names)
assert any(name and name.startswith("tool.") for name in operation_names)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be handy to have a test where the agent actually suspends mid-run and then succeeds on a later invocation by replaying its checkpointed model and tool steps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants