If a tool takes three minutes (terraform plan, warehouse query, image build), do not hold the Bedrock turn open. Emit an event, return a correlation id, and let the agent poll get_job — or resume via Step Functions callback. Day 34 makes EventBridge the async backbone.
⚡ TL;DR: Sync tools for <2s work; async via EventBridge for longer. Persist job state in DynamoDB with idempotency. Teach the model the start/get contract; cap polls in the graph.
Pattern
start_job(args, idempotencyKey)
→ DynamoDB PENDING (conditional)
→ PutEvents JobRequested
→ return {jobId}
Worker rule → run → SUCCEEDED|FAILED + result pointer
get_job(jobId) → status for next agent turn
import uuid, time, json, boto3
ddb = boto3.resource("dynamodb").Table("AgentJobs")
eb = boto3.client("events")
def start_job(tenant: str, tool: str, args: dict, idem: str) -> dict:
job_id = str(uuid.uuid4())
try:
ddb.put_item(
Item={
"pk": f"tenant#{tenant}",
"sk": f"idem#{idem}",
"jobId": job_id,
"status": "PENDING",
"tool": tool,
"createdAt": int(time.time()),
},
ConditionExpression="attribute_not_exists(sk)",
)
except ddb.meta.client.exceptions.ConditionalCheckFailedException:
prev = ddb.get_item(Key={"pk": f"tenant#{tenant}", "sk": f"idem#{idem}"})["Item"]
return {"jobId": prev["jobId"], "deduped": True}
eb.put_events(Entries=[{
"Source": "agent.tools",
"DetailType": "JobRequested",
"Detail": json.dumps({"jobId": job_id, "tenant": tenant, "tool": tool, "args": args}),
"EventBusName": "agents",
}])
return {"jobId": job_id, "deduped": False}
Why EventBridge
Rules fan out to workers, metrics, and security audit without hard-coding consumers. You can still target SQS for buffering. Schema discipline prevents silent payload drift.
Production checklist
- [ ] Job table with status enum + TTL
- [ ] Idempotency on start_job
- [ ] DLQ on worker failures
- [ ] Prompt/tool docs describe async contract
- [ ] Trace
jobIdacross EventBridge → worker - [ ] Poll cap in Step Functions / agent loop
Series navigation
Last updated September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
