Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

koda-agent-runtime

Runtime compartido para agentes Koda A2A sobre Amazon Bedrock AgentCore. Extrae en un solo paquete versionado las piezas que cada koda-agent-* repite: constantes de custom headers, middleware FastAPI, cliente HTTP hacia el registry, decoradores de tools, loader del agent.yaml, y un bootstrap build_agent_app(cfg) que ensambla Strands + A2A + FastAPI en una llamada.

Ver KODA_AGENT_RUNTIME_ARCHITECTURE.md en el monorepo koda-platform para el diseño completo, precedente (koda-mcp-access), roadmap y compatibilidad.

Instalación

Elige el extra según lo que consuma el agente:

# El mínimo — headers, middleware, auth, registry client, config loader.
"koda-agent-runtime>=0.2.0,<0.3"

# El agente típico — además Strands + A2A + Bedrock (y AnthropicModel) para
# build_agent_app.
"koda-agent-runtime[bootstrap]>=0.2.0,<0.3"

# El stack CDK del agente — Construct KodaAgentRuntime.
"koda-agent-runtime[cdk]>=0.2.0,<0.3"

Mientras 0.2 está en release candidate (0.2.0rc1), >=0.2.0 no la toma (PEP 440: 0.2.0rc1 < 0.2.0). Para probarla, fija "koda-agent-runtime[bootstrap]>=0.2.0rc1,<0.3": acepta la RC y, cuando salga, toma 0.2.0 sin cambiar el pin. Los agentes que fijan <0.2 no la toman.

0.2 rompe compatibilidad con 0.1.x. El agente ya no recibe ni reenvía bearers: se eliminan get_bearer, set_context, KODA_AUTHZ_HEADER y el header Koda-Authorization del allowlist. La identidad es un CallerContext verificado por request (get_caller()) y las llamadas al registry van firmadas (ver "Auth M2M"). Un agente que se invoca directo por InvokeAgentRuntime, sin identidad, y no llama a nada puede tomar 0.2 con KODA_AGENT_M2M=off.

El extra bootstrap instala strands-agents[a2a,anthropic], de modo que build_agent_app soporta tanto provider: bedrock como provider: anthropic (este último vía AnthropicModel, con ANTHROPIC_API_KEY en el entorno).

Uso — un agente en 10 líneas

src/agent.py:

from pathlib import Path
import uvicorn
from koda_agent_runtime.config import load_agent_config
from koda_agent_runtime.app import build_agent_app

_BASE = Path(__file__).resolve().parent.parent
app = build_agent_app(load_agent_config(_BASE / "agent.yaml"), base_dir=_BASE)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=9000)

agent.yaml:

name: koda-agent-example
version: 0.1.0
description: |
  Un agente de ejemplo.

model:
  provider: bedrock              # bedrock | anthropic
  model_id: us.amazon.nova-lite-v1:0
  temperature: 0.3               # opcional; OMITIR en modelos que la tienen
                                 # deprecada (Sonnet 5, Opus 4.8) o dan error
  max_tokens: 4000

tools:
  - discover_skills
  - fetch_registry_skill
  - invoke_agent

Módulos

Módulo Responsabilidad
koda_agent_runtime.headers Constantes KODA_*_HEADER + ALLOWLISTED_HEADERS (para agentcore configure --request-header-allowlist).
koda_agent_runtime.context CallerContext por request en un ContextVar: get_caller(), get_request_id(), delegation_claims().
koda_agent_runtime.middleware KodaIdentityMiddleware (ASGI puro, para app.add_middleware) y el helper koda_headers_middleware(app). Verifica la firma del registry y arma el CallerContext (ver KODA_AGENT_M2M).
koda_agent_runtime.auth check_m2m_config, IdentityVerifier (koda-agent-identity-v1), AgentM2MAuth (httpx.Auth que firma koda-agent-m2m-v1), m2m_headers y el keyring agent-m2m.
koda_agent_runtime.registry discover_agents, discover_skills, fetch_skill_bundle, invoke_peer — hablan con el registry firmando koda-agent-m2m-v1.
koda_agent_runtime.tools Decoradores @strands.tools.tool sobre los helpers de registry. build_tools(cfg) filtra por lo declarado en agent.yaml.tools.
koda_agent_runtime.config load_agent_config(path) → dataclass tipado AgentConfig.
koda_agent_runtime.app build_agent_app(cfg, base_dir) → FastAPI con Strands Agent + A2AServer + middleware montados. Requiere [bootstrap] extra.

Contrato de headers Koda-*

koda-proxy (broker del registry) inyecta estos custom headers al invocar tu runtime. AgentCore solo forwardea headers con prefix X-Amzn-Bedrock-AgentCore-Runtime-Custom- y que estén en el allowlist del runtime: usa ALLOWLISTED_HEADERS completo (más los extras de tu agente).

Header Contenido Estable en cadenas A→B→C
Koda-Sub Usuario humano original. Sí.
Koda-Email Email del usuario. Sí.
Koda-Roles Groups Okta del usuario. Sí.
Koda-Chain-Depth Hops desde el usuario. +1 por hop.
Koda-Request-Id uuid para trace end-to-end. Sí.
Koda-Agent-Path Path del agente que recibe. N/A.
Koda-Caller-Type user | agent. Depende del hop.
Koda-Caller-Agent agent:<name> del agente que llama, o vacío. Depende del hop.
Koda-Auth-Groups Grupos de autorización, separados por espacio. Sí.
Koda-Delegation Ticket de delegación (JWT opaco; se reenvía, no se verifica). Sí.
Koda-Signed-At, Koda-Key-Id, Koda-Signature Firma koda-agent-identity-v1 del registry sobre Sub…Delegation. Por request.

Todos los strings viven en koda_agent_runtime.headers como constantes. Nunca los repitas en tu código.

Auth M2M (0.2.0)

Una sola flag, KODA_AGENT_M2M:

Valor Entrada Salida (registry.py, AgentM2MAuth) Variables obligatorias
on (default, también sin definir) Verifica la firma koda-agent-identity-v1 del registry: sin firma válida, 403. /ping y /.well-known/* no se verifican. Firma koda-agent-m2m-v1 como agent:<KODA_AGENT_NAME> y reenvía X-Koda-Delegation. KODA_AGENT_NAME, KODA_AGENT_M2M_SECRET_ID
off No verifica; el CallerContext queda vacío (verified=False). Falla con KODA_AGENT_M2M=off: agent is outside the M2M network; nunca manda una request sin firmar. Ninguna
Variable Ejemplo Qué es
KODA_AGENT_NAME koda-qa-test-design El agente firma y verifica como agent:<name>.
KODA_AGENT_M2M_SECRET_ID ai-projects/koda-platform/agent-m2m Keyring en Secrets Manager (caché de 300 s, kid actual y anterior). El rol del runtime necesita secretsmanager:GetSecretValue sobre el secret (y kms:Decrypt si usa una CMK).

Cualquier otro valor de KODA_AGENT_M2M, o on sin las dos variables, falla al arrancar: un typo no puede apagar la seguridad. El valor efectivo se loguea al arrancar. La firma la implementa koda_agent_runtime._vendor.koda_signing (copia de koda-mcp-access 1.8.0); los vectores compartidos están en tests/vectors/.

Para firmar un cliente httpx propio (p. ej. el MCPClient de Strands), construye el AgentM2MAuth dentro de la request, porque captura la delegación y el request_id del caller al construirse:

from koda_agent_runtime.auth import AgentM2MAuth

auth = AgentM2MAuth()  # agent:<KODA_AGENT_NAME>, keyring de KODA_AGENT_M2M_SECRET_ID

Anti-patrones

  • No lances threads propios sin el contexto: un threading.Thread pelado no ve el CallerContext. Usa asyncio.to_thread o contextvars.copy_context().run (Strands >= 1.0 ya lo hace con las tools).
  • No firmes SigV4 desde el agente para invocar peers. Delega via invoke_peer(<path>, <msg>) — el registry firma por ti.
  • No trates un CallerContext vacío como un usuario: con KODA_AGENT_M2M=off (o en /ping) no hay identidad. Para decisiones de seguridad, exige get_caller().verified.

Desarrollo

uv sync --all-extras   # los tests importan strands (extra bootstrap)
uv run pytest
uv run ruff check .
uv build

Release (manual, no hay CI de publicación):

# 1. version en pyproject.toml (p. ej. 0.2.0rc1 / 0.2.0) y uv lock
uv lock
uv run pytest && uv run ruff check .
rm -rf dist && uv build && uvx twine check dist/*
# 2. commit, tag vX.Y.Z y push del branch y del tag
# 3. publicar (el token vive en .pypi-token, que NUNCA se versiona)
uv publish --token "$(cat .pypi-token)" dist/*

Una versión subida a PyPI no se puede reemplazar (solo yank): verifica antes.

Versionado

  • v0.x — alpha, breaking changes tolerados. Todos los agentes en migración inicial.
  • v1.0.0 — cuando la API sea estable y >=3 agentes la consuman en producción. A partir de acá, SemVer estricto.

Metadata

Release files for koda-agent-runtime 0.2.0rc1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for koda-agent-runtime 0.2.0rc1
File Size Uploaded Provenance Actions
koda_agent_runtime-0.2.0rc1.tar.gz 158.3 kB Without provenance Details for koda_agent_runtime-0.2.0rc1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for koda-agent-runtime 0.2.0rc1
File Interpreter ABI Platform Actions
koda_agent_runtime-0.2.0rc1-py3-none-any.whl Python 3 none any Details for koda_agent_runtime-0.2.0rc1-py3-none-any.whl

Total release size: 198.3 kB

Release files / koda_agent_runtime-0.2.0rc1.tar.gz

Download URL koda_agent_runtime-0.2.0rc1.tar.gz
Size 158.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9a838baa7302005dfab77eeccbd3b78423ed78302cd91f2be0056d78ae9b0d6e
BLAKE2b-256 checksum
How to use checksums
734555fc427dac8df955d8369cd55855ac6bf7323f3072a8cf978c5bcdd14b8e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / koda_agent_runtime-0.2.0rc1-py3-none-any.whl

Download URL koda_agent_runtime-0.2.0rc1-py3-none-any.whl
Size 40.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cf9c91f39ba1ee3b72aa8a10507a19d41f509b6e1c77e3fa92fa93da374a9cfc
BLAKE2b-256 checksum
How to use checksums
3c5eafdcb9cab51c85fe2b0dff91356aa8653cbcd4e17f8449e2b1a9b0495bbf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for koda-agent-runtime 0.2.0rc1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page