Agent Governance Foundation

AWS Lambda integration

No Lambda-specific adapter exists, and none is needed — guard_tool(), the same decorator the MCP integration uses, already works unmodified on a raw (event, context) handler.

Install

pip install agf-sdk

No extra needed — guard_tool ships in the core package. Requires agf-sdk ≥ 0.7.0 (see below).

Set your API key

export AGF_API_KEY=agfk_your_key_here

Generate a key from Settings → API Keys.

Guard your handler

Lambda calls a handler as a plain, synchronous, positional function — never async. guard_tool()is fully generic over its wrapped function's arguments, so it applies with no adaptation:

import os
from agf.client import AGFClient
from agf.keys import build_self_signed_chain
from agf.mcp import guard_tool

AGF_AGENT_ID = "did:agf:my-lambda-fn"
# Module-level — reused across warm-container invocations.
client = AGFClient(api_key=os.environ["AGF_API_KEY"])


def _chain_provider(event, context):
    # Built fresh per call — a chain built once at cold-start expires in
    # 5 minutes, and a warm container can sit idle past that.
    return build_self_signed_chain(AGF_PRIVATE_KEY_PEM, AGF_AGENT_ID, "lambda:issue_refund", "agf")


@guard_tool(
    client,
    agent_id=AGF_AGENT_ID,
    action_type="lambda:issue_refund",
    chain_provider=_chain_provider,
    validate_execution=True,
    report_outcome=True,
)
def handler(event, context):
    order_id = event["order_id"]
    amount = event["amount"]
    result = process_refund(order_id, amount)
    return {"statusCode": 200, "body": result}

Warm containers need agf-sdk ≥ 0.7.0

A warm Lambda container reuses the same module-level client across many invocations. agf-sdk 0.7.0 hardened the sync/async bridge guard_tool() uses so a shared client stays safe across repeated calls — pin agf-sdk>=0.7.0 in your Lambda deployment package.

If your handler already has other decorators

Common with observability toolkits like AWS Lambda Powertools. Apply guard_tool() innermost — closest to def handler— so the outer decorators capture AGF's own call too:

# guard_tool composes with any other decorators your handler already
# has — place it innermost, right above def handler, so your existing
# observability decorators (logging, tracing, metrics) wrap AGF's own
# call too:
@init_environment_variables(model=HandlerEnvVars)
@logger.inject_lambda_context(...)
@metrics.log_metrics
@tracer.capture_lambda_handler(capture_response=False)
@guard_tool(client, agent_id=AGF_AGENT_ID, action_type="lambda:issue_refund",
            chain_provider=_chain_provider, validate_execution=True, report_outcome=True)
def handler(event, context):
    ...

Related