Observed since 20 Oct, 22:31 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Agent Kernel - Unified AI Agents Runtime
Agent Kernel is a lightweight AI agent runtime and adapter layer for building and running AI agents across multiple frameworks. Migrate your existing agents to Agent Kernel and instantly utilize pre-built execution and testing capabilities. Deploy the same agent code without modification — see the "Multi-Cloud Deployment" section below for supported platforms.
KnowledgeBase interface with ChromaDB, Neo4j, Starburst/Trino and Open Knowledge Format bundle (local directory or S3) backends via KnowledgeBuilderlocal_subprocess, docker, kubernetes, e2b, daytona, ec2_ssm), workload profiles, policy enforcement, per-user identity, and a queue-decoupled broker for long-running executionsSecretManager resolves API keys and passwords environment-first, falling back to a pluggable provider (env, aws_ssm for AWS SSM Parameter Store, or your own) with a TTL'd process cacheschedule.at/schedule.cron) with a management REST API, five agent-facing tools, and pluggable provider (local, eventbridge) and store (in_memory, redis, valkey, dynamodb) backendsstatus: "PAUSED" with HTTP 202, a resume block carrying approved/denied/cancelled decisions, supported on OpenAI Agents SDK, LangGraph, Pydantic AI and Google ADK over REST, streaming and AG-UIpip install agentkernel
Install optional knowledge base extras as needed:
pip install "agentkernel[chromadb]"
pip install "agentkernel[neo4j]"
pip install "agentkernel[trino]"
Open Knowledge Format bundles need no extra - pyyaml is a core dependency. Serving a bundle from S3
uses the aws extra: pip install "agentkernel[aws]".
For LLM-based thread naming with Conversation Thread Support:
pip install "agentkernel[thread]"
For the AG-UI server (AGUIRequestHandler):
pip install "agentkernel[agui]"
For the sandbox providers (the local_subprocess provider needs no extra; ec2_ssm rides
the aws extra):
pip install "agentkernel[sandbox-docker]" # docker provider
pip install "agentkernel[kubernetes]" # kubernetes provider (pod per sandbox)
pip install "agentkernel[e2b]" # e2b cloud provider
pip install "agentkernel[daytona]" # daytona cloud provider
pip install "agentkernel[aws]" # ec2_ssm provider (boto3)
For the aws_ssm secret provider (AWS SSM Parameter Store):
pip install "agentkernel[aws]"
For cron parsing with the Scheduling capability (the eventbridge provider rides the aws extra):
pip install "agentkernel[cron]"
Requirements:
from crewai import Agent as CrewAgent
from agentkernel.cli import CLI
from agentkernel.crewai import CrewAIModule
general_agent = CrewAgent(
role="general",
goal="Agent for general questions",
backstory="You provide assistance with general queries. Give direct and short answers",
verbose=False,
)
math_agent = CrewAgent(
role="math",
goal="Specialist agent for math questions",
backstory="You provide help with math problems. Explain your reasoning at each step and include examples. \
If prompted for anything else you refuse to answer.",
verbose=False,
)
# Register agents with Agent Kernel
CrewAIModule([general_agent, math_agent])
if __name__ == "__main__":
CLI.main()
from langgraph.graph import StateGraph
from agentkernel.cli import CLI
from agentkernel.langgraph import LangGraphModule
# Build and compile your graph
sg = StateGraph(...)
compiled = sg.compile()
compiled.name = "assistant"
LangGraphModule([compiled])
if __name__ == "__main__":
CLI.main()
from agents import Agent as OpenAIAgent
from agentkernel.cli import CLI
from agentkernel.openai import OpenAIModule
general_agent = OpenAIAgent(
name="general",
handoff_description="Agent for general questions",
instructions="You provide assistance with general queries. Give short and direct answers.",
)
OpenAIModule([general_agent])
if __name__ == "__main__":
CLI.main()
from google.adk.agents import Agent
from agentkernel.cli import CLI
from agentkernel.adk import GoogleADKModule
from google.adk.models.lite_llm import LiteLlm
# Create Google ADK agents
math_agent = Agent(
name="math",
model=LiteLlm(model="openai/gpt-4o-mini"),
description="Specialist agent for math questions",
instruction="""
You provide help with math problems.
Explain your reasoning at each step and include examples.
If prompted for anything else you refuse to answer.
""",
)
GoogleADKModule([math_agent])
if __name__ == "__main__":
CLI.main()
Agent Kernel includes an interactive CLI for local development and testing.
Available Commands:
!h, !help — Show help!ld, !load <module_name> — Load a Python module containing agents!ls, !list — List registered agents!s, !select <agent_name> — Select an agent!n, !new — Start a new session!q, !quit — ExitUsage:
python demo.py
Then interact with your agents:
(assistant) >> !load my_agents
(assistant) >> !select researcher
(researcher) >> What is the latest news on AI?
Supported Cloud Platforms: AWS, Azure, GCP
Deploy your agents to AWS, Azure, or GCP using the built-in cloud deployment handlers.
Deploy your agents as serverless functions using the built-in Lambda handler.
from openai import OpenAI
from agents import Agent as OpenAIAgent
from agentkernel.aws import Lambda
from agentkernel.openai import OpenAIModule
client = OpenAI()
assistant = OpenAIAgent(name="assistant")
OpenAIModule([assistant])
handler = Lambda.handler
Note that this is just the simple serverless version. A more advanced serverless deployment mode, which uses queues for scalability, is also available. For queue-backed execution modes and response-store configuration, see the AWS Serverless Deployment guide.
The AWS serverless handler accepts both a direct BaseRunRequest payload and the normalized BaseRequest envelope. If a flat run payload is provided, Agent Kernel generates a request_id and normalizes it before processing.
Accepted payloads:
{
"prompt": "Hello agent",
"agent": "assistant",
"session_id": "user-123"
}
{
"request_id": "req-123",
"user_id": "user-123",
"body": {
"prompt": "Hello agent",
"agent": "assistant",
"session_id": "user-123"
}
}
Deploy your agents as Azure Functions using the built-in Azure handler.
from openai import OpenAI
from agents import Agent as OpenAIAgent
from agentkernel.azure import AzureFunctions
from agentkernel.openai import OpenAIModule
client = OpenAI()
assistant = OpenAIAgent(name="assistant")
OpenAIModule([assistant])
handler = AzureFunctions.handler
Request Format:
{
"request_id": "req-123",
"user_id": "user-123",
"body": {
"prompt": "Hello agent",
"agent": "assistant",
"session_id": "user-123"
}
}
Azure Functions also accepts the normalized envelope, and flat run payloads are normalized in the same way before the request reaches the agent runtime.
Response Format:
{
"result": "Agent response here"
}
Status Codes:
200 — Success400 — No agent available500 — Unexpected errorDeploy your agents to GCP Cloud Run using the built-in CloudRun handler.
from agentkernel.gcp import CloudRun
from agentkernel.openai import OpenAIModule
OpenAIModule([...])
@CloudRun.register("/app", method="GET")
def app_handler() -> dict:
return {"status": "ok"}
def main() -> None:
CloudRun.run()
if __name__ == "__main__":
main()
CloudRun is the GCP equivalent of Lambda (AWS) and AzureFunctions (Azure). It wraps RESTAPI and starts a FastAPI/uvicorn server. Custom routes are registered with @CloudRun.register(path, method). Use CloudRun.run() instead of RESTAPI.run() when deploying to GCP.
For full Terraform deployment configuration, see ak-deployment/ak-gcp/ or the GCP deployment docs.
Deploy the queue pipeline to any Kubernetes cluster with the official Helm chart: an io-handler Deployment (REST API + Response Handler), an agent-runner Deployment, and an optional WebSocket gateway, over Kafka or NATS JetStream (or SQS on EKS). Your image supplies one entry file per component:
# app_io_handler.py
from agentkernel.pipeline import IOHandler
IOHandler.run()
# app_agent_runner.py
from agentkernel.openai import OpenAIModule
from agentkernel.pipeline import AgentRunner
OpenAIModule([...])
AgentRunner.run()
The chart injects broker and store connections as AK_* environment variables. See
ak-deployment/ak-k8s/,
the On-Prem / Kubernetes docs,
and the end-to-end example at
examples/k8s/openai-queue-mode.
Agent Kernel can be configured via environment variables, .env files, or YAML/JSON configuration files.
Values are loaded in the following order (highest precedence first):
.env file)By default, Agent Kernel looks for ./config.yaml in the current working directory.
Override the config file path:
export AK_CONFIG_PATH_OVERRIDE=config.json
# or
export AK_CONFIG_PATH_OVERRIDE=conf/agent-kernel.yaml
Supported formats: .yaml, .yml, .json
Field: logging.ak.level
Type: string
Default: WARNING
Description: Agent Kernel logger level (INFO, DEBUG, ERROR, WARNING, CRITICAL)
Environment Variable: AK_LOGGING__AK__LEVEL
Field: logging.system.level
Type: string
Default: WARNING
Description: System/root logger level (INFO, DEBUG, ERROR, WARNING, CRITICAL)
Environment Variable: AK_LOGGING__SYSTEM__LEVEL
Configure where agent sessions are stored (supports multi-cloud storage backends).
session.typein_memory, redis, valkey (AWS), dynamodb (AWS), cosmosdb (Azure), firestore (GCP)in_memoryAK_SESSION__TYPERequired when session.type=redis:
URL
session.redis.urlredis://localhost:6379rediss:// for SSLAK_SESSION__REDIS__URLTTL (Time to Live)
session.redis.ttl604800 (7 days)AK_SESSION__REDIS__TTLKey Prefix
session.redis.prefixak:sessions:AK_SESSION__REDIS__PREFIXRequired when session.type=valkey (requires the agentkernel[valkey] extra). Valkey
is the open-source, Linux Foundation-governed fork of Redis — wire-compatible with Redis and
available on AWS ElastiCache at a lower price point than the Redis OSS engine:
URL
session.valkey.urlvalkey://localhost:6379valkeys:// for SSLAK_SESSION__VALKEY__URLTTL (Time to Live)
session.valkey.ttl604800 (7 days)AK_SESSION__VALKEY__TTLKey Prefix
session.valkey.prefixak:sessions:AK_SESSION__VALKEY__PREFIXMounting AgentThreadRequestHandler (from agentkernel.thread) instead of the default REST handler
enables persistent, named conversation threads keyed by session_id: it serves the standard chat routes
with thread recording, plus the read routes (GET /api/v1/threads and
GET /api/v1/threads/{session_id}, optionally protected by a pluggable Authoriser). The thread
block in the configuration only selects the store backend and naming. On the thread handler's chat
routes user_id is required, and a thread is auto-created on a session's first request. Sending
thread_name on any chat request sets or renames the thread's display name and locks it against automatic
naming. Threads created without an explicit thread_name are
named by a pluggable naming strategy — by default an LLM call derives a concise title from the first prompt
(falling back to a prefix of the prompt when litellm or an API key is unavailable). Attachments in thread
mode additionally require multimodal.enabled: true with a shared attachment store (in_memory, redis, or
dynamodb — session_cache is rejected). See examples/api/thread-openai and
examples/api/multimodal/thread-openai.
Field: thread.type
Type: string
Options: in_memory, redis, valkey, dynamodb (AWS), firestore (GCP), cosmosdb (Azure)
Default: in_memory
Environment Variable: AK_THREAD__TYPE
Naming Model
thread.naming.modelgpt-4o-minithread extra — pip install "agentkernel[thread]" — and an API key in the environment; falls back to a truncated prompt prefix otherwise)AK_THREAD__NAMING__MODELAuto-name Max Length
thread.naming.max_length80AK_THREAD__NAMING__MAX_LENGTHRequired when thread.type=redis:
URL
thread.redis.urlredis://localhost:6379rediss:// for SSLAK_THREAD__REDIS__URLTTL (Time to Live)
thread.redis.ttl2592000 (30 days)AK_THREAD__REDIS__TTLKey Prefix
thread.redis.prefixak:thread:AK_THREAD__REDIS__PREFIXRequired when thread.type=valkey. Requires the valkey extra (pip install "agentkernel[valkey]"):
URL
thread.valkey.urlvalkey://localhost:6379valkeys:// for SSLAK_THREAD__VALKEY__URLTTL (Time to Live)
thread.valkey.ttl2592000 (30 days)AK_THREAD__VALKEY__TTLKey Prefix
thread.valkey.prefixak:thread:AK_THREAD__VALKEY__PREFIXUsed when thread.type=dynamodb:
Table Name
thread.dynamodb.table_nameak-agent-threadssession_id (S) and a sort key named sk (S)AK_THREAD__DYNAMODB__TABLE_NAMETTL (Time to Live)
thread.dynamodb.ttl0 (disabled)AK_THREAD__DYNAMODB__TTLUsed when thread.type=firestore:
Collection Name
thread.firestore.collection_nameak-agent-threadssession_idAK_THREAD__FIRESTORE__COLLECTION_NAMEProject ID
thread.firestore.project_idnull (inferred from Application Default Credentials)AK_THREAD__FIRESTORE__PROJECT_IDDatabase ID
thread.firestore.database_idnull (the (default) database)AK_THREAD__FIRESTORE__DATABASE_IDTTL (Time to Live)
thread.firestore.ttl0 (disabled)AK_THREAD__FIRESTORE__TTLRequired when thread.type=cosmosdb:
Connection String
thread.cosmosdb.connection_stringsession_id. No TTL supportAK_THREAD__COSMOSDB__CONNECTION_STRINGTable Name
thread.cosmosdb.table_nameakagentthreadsAK_THREAD__COSMOSDB__TABLE_NAMEThe presence of a schedule block enables deferred and recurring chat execution: a chat request carrying a
schedule block (at for one-time, cron for recurring, plus timezone and session_mode) is not run —
it is registered as a scheduled task and acknowledged with HTTP 202. When an occurrence is due, the provider
delivers the stored prompt into the input queue as a plain chat request, so scheduling requires the queue
execution pipeline. The block also injects five agent tools (create_schedule, list_schedules,
get_schedule, update_schedule, delete_schedule). The management routes
(GET/PUT/DELETE /api/v1/schedules) are not mounted from config: the application mounts
ScheduleRESTRequestHandler itself — IOHandler.run(handlers=[ScheduleRESTRequestHandler()]) —
passing an optional pluggable Authoriser to the handler to protect them. Every scheduling request
needs a user_id: it is the owner the task is stored under and the identity later reads and changes
are checked against. A bare schedule: block works for local development — its defaults are the
local provider and the in_memory store. See examples/api/schedule-openai.
Provider Type
schedule.provider.typelocallocal (in-process scheduler thread; requires the in_memory transport and store),
eventbridge (AWS EventBridge Scheduler; requires the sqs transport and the aws extra), or a dotted
path to a ScheduleProvider subclassAK_SCHEDULE__PROVIDER__TYPEStore Type
schedule.store.typein_memoryin_memory, redis, valkey, dynamodb, or a dotted path to a ScheduleStore subclassAK_SCHEDULE__STORE__TYPETool Scoping
schedule.agentsnull (all agents)AK_SCHEDULE__AGENTSRequired when schedule.provider.type=eventbridge. All three are supplied by the AWS Terraform modules
when enable_scheduling = true; a missing one fails at startup with an AKConfigError.
Group Name
schedule.provider.eventbridge.group_nameAK_SCHEDULE__PROVIDER__EVENTBRIDGE__GROUP_NAMERole ARN
schedule.provider.eventbridge.role_arnAK_SCHEDULE__PROVIDER__EVENTBRIDGE__ROLE_ARNQueue ARN
schedule.provider.eventbridge.queue_arnAK_SCHEDULE__PROVIDER__EVENTBRIDGE__QUEUE_ARNRequired when schedule.store.type=redis (or valkey, with schedule.store.valkey.* / AK_SCHEDULE__STORE__VALKEY__*).
URL
schedule.store.redis.urlredis://localhost:6379rediss:// for SSLAK_SCHEDULE__STORE__REDIS__URLKey Prefix
schedule.store.redis.prefixak:schedule:AK_SCHEDULE__STORE__REDIS__PREFIXTTL (Time to Live)
schedule.store.redis.ttl0 (disabled)AK_SCHEDULE__STORE__REDIS__TTLRequired when schedule.store.type=dynamodb. The table needs a partition key named task_id (S) and no
sort key; the AWS Terraform modules create it when create_dynamodb_schedule_table = true.
Table Name
schedule.store.dynamodb.table_nameak-agent-schedulesAK_SCHEDULE__STORE__DYNAMODB__TABLE_NAMETTL (Time to Live)
schedule.store.dynamodb.ttl0 (disabled)AK_SCHEDULE__STORE__DYNAMODB__TTLSecretManager.current().get("OPENAI_API_KEY") resolves a secret by the same environment-variable-style
name the SDKs already read (^[A-Z][A-Z0-9_]*$). Resolution order is fixed: a set, non-empty environment
variable always wins, then the process cache, then the configured provider. A resolved value is returned to
the caller and never written back to the environment, so hand it to the SDK explicitly
(set_default_openai_key(...)). A miss raises SecretNotFoundError unless a default is passed; a provider
failure raises SecretError even with a default. The capability is always available — there is no
enabled flag; selecting a provider other than env is the only opt-in. See examples/cli/openai-secret.
Provider Type
secret.provider.typeenvenv (the process environment), aws_ssm (AWS SSM Parameter Store; requires
secret.prefix and the aws extra — OPENAI_API_KEY is read from /ak/<prefix>/openai_api_key), or a
dotted path to a SecretProvider subclassAK_SECRET__PROVIDER__TYPEPrefix
secret.prefix""aws_ssm, ignored by env. Injected by the AWS Terraform modules when ssm_enabled = trueAK_SECRET__PREFIXCache TTL
secret.cache_ttl3000 disables caching); the
rotation-pickup window for values read per callAK_SECRET__CACHE_TTLConfigure queue-backed and serverless execution behavior.
Execution Mode
execution.moderest_sync, rest_async, stream, asyncNoneAK_EXECUTION__MODEQueues
Field: execution.queues
Description: Queue settings used by the queue execution pipeline (in-process by default, or serverless/containerized backends)
Transport Type
execution.queues.typein_memory, sqs, kafka, nats, or a dotted path to a QueueTransport subclassexecution.queues block is declaredtype is a configuration error. Omitting the block entirely leaves in_memory — a zero-dependency, in-process transport for local development and single-process deployments.AK_EXECUTION__QUEUES__TYPEInput Queue URL
execution.queues.input.urlNonesqs transport only)AK_EXECUTION__QUEUES__INPUT__URLOutput Queue URL
execution.queues.output.urlNonesqs transport only)AK_EXECUTION__QUEUES__OUTPUT__URLInput Queue Max Receive Count
execution.queues.input.max_receive_count3AK_EXECUTION__QUEUES__INPUT__MAX_RECEIVE_COUNTOutput Queue Max Receive Count
execution.queues.output.max_receive_count3AK_EXECUTION__QUEUES__OUTPUT__MAX_RECEIVE_COUNTInput Queue Consumer Count
execution.queues.input.no_of_consumers5AK_EXECUTION__QUEUES__INPUT__NO_OF_CONSUMERSOutput Queue Consumer Count
execution.queues.output.no_of_consumers5AK_EXECUTION__QUEUES__OUTPUT__NO_OF_CONSUMERSIn-Memory Transport Ack Wait
execution.queues.in_memory.ack_wait300.0In-Memory Transport Dedup Window
execution.queues.in_memory.dedup_window300.0message_deduplication_id is droppedKafka Bootstrap Servers
execution.queues.kafka.bootstrap_serverslocalhost:9092AK_EXECUTION__QUEUES__KAFKA__BOOTSTRAP_SERVERSKafka Input Topic
execution.queues.kafka.input_topicagent-inputAK_EXECUTION__QUEUES__KAFKA__INPUT_TOPICKafka Output Topic
execution.queues.kafka.output_topicagent-outputAK_EXECUTION__QUEUES__KAFKA__OUTPUT_TOPICKafka Consumer Group Id
execution.queues.kafka.group_idagent-kernelAK_EXECUTION__QUEUES__KAFKA__GROUP_IDKafka Dead-Letter Topic Suffix
execution.queues.kafka.dlq_suffix.dlqAK_EXECUTION__QUEUES__KAFKA__DLQ_SUFFIXKafka Retry Backoff
execution.queues.kafka.retry_backoff2.0AK_EXECUTION__QUEUES__KAFKA__RETRY_BACKOFFKafka Delivery Timeout
execution.queues.kafka.delivery_timeout30.0AK_EXECUTION__QUEUES__KAFKA__DELIVERY_TIMEOUTKafka Metadata Timeout
execution.queues.kafka.metadata_timeout5.0AK_EXECUTION__QUEUES__KAFKA__METADATA_TIMEOUTKafka Client Config
execution.queues.kafka.client_config{}confluent-kafka producer and consumer configs (SASL, TLS, tuning); set via config.yaml, not individually exported as environment variablesNATS Server URL
execution.queues.nats.urlnats://localhost:4222AK_EXECUTION__QUEUES__NATS__URLNATS Input Stream
execution.queues.nats.input_streamAGENT_REQUESTSAK_EXECUTION__QUEUES__NATS__INPUT_STREAMNATS Input Subject Prefix
execution.queues.nats.input_subject_prefixchat.reqAK_EXECUTION__QUEUES__NATS__INPUT_SUBJECT_PREFIXNATS Output Stream
execution.queues.nats.output_streamAGENT_REPLIESAK_EXECUTION__QUEUES__NATS__OUTPUT_STREAMNATS Output Subject Prefix
execution.queues.nats.output_subject_prefixchat.outAK_EXECUTION__QUEUES__NATS__OUTPUT_SUBJECT_PREFIXNATS Partitions
execution.queues.nats.partitions32no_of_consumers x replicas. Changing it re-maps sessions, so size it up front (idle partitions cost almost nothing)AK_EXECUTION__QUEUES__NATS__PARTITIONSNATS Ack Wait
execution.queues.nats.ack_wait300.0AK_EXECUTION__QUEUES__NATS__ACK_WAITNATS Retry Backoff
execution.queues.nats.retry_backoff2.0AK_EXECUTION__QUEUES__NATS__RETRY_BACKOFFNATS Duplicate Window
execution.queues.nats.duplicate_window300.0AK_EXECUTION__QUEUES__NATS__DUPLICATE_WINDOWNATS Max Age
execution.queues.nats.max_age86400.0AK_EXECUTION__QUEUES__NATS__MAX_AGENATS Request Timeout
execution.queues.nats.request_timeout10.0AK_EXECUTION__QUEUES__NATS__REQUEST_TIMEOUTNATS Auto Provision
execution.queues.nats.auto_provisionfalseAK_EXECUTION__QUEUES__NATS__AUTO_PROVISIONQueue Batch Size
execution.queues.batch_sizeNoneAK_EXECUTION__QUEUES__BATCH_SIZE — do not set in config.yaml.AK_EXECUTION__QUEUES__BATCH_SIZEResponse Store
Field: execution.response_store
Description: Response persistence settings used by the serverless response handler
Type
execution.response_store.typein_memory, redis, valkey, dynamodb, or a dotted path to a ResponseStore subclassconfig.yaml; this value is not exported as an environment variable. Defaults to an in-process in_memory store when unset and no other backend is configured.Retry Count
execution.response_store.retry_count5AK_EXECUTION__RESPONSE_STORE__RETRY_COUNTDelay
execution.response_store.delay5AK_EXECUTION__RESPONSE_STORE__DELAYRedis Backend
execution.response_store.redisAK_EXECUTION__RESPONSE_STORE__REDIS__URL, AK_EXECUTION__RESPONSE_STORE__REDIS__PREFIX, AK_EXECUTION__RESPONSE_STORE__REDIS__TTLValkey Backend
execution.response_store.valkeyAK_EXECUTION__RESPONSE_STORE__VALKEY__URL, AK_EXECUTION__RESPONSE_STORE__VALKEY__PREFIX, AK_EXECUTION__RESPONSE_STORE__VALKEY__TTLagentkernel[valkey] extra)DynamoDB Backend
execution.response_store.dynamodbAK_EXECUTION__RESPONSE_STORE__DYNAMODB__TABLE_NAME, AK_EXECUTION__RESPONSE_STORE__DYNAMODB__TTLUse the built-in in_memory response store for local development and single-process deployments (zero extra services required), or Redis, Valkey, or DynamoDB for distributed/serverless deployments. The runtime accepts BaseRunRequest payloads directly, normalizes them internally when queueing is required, and uses request_id plus optional user_id as queue message attributes.
Configure the REST API server (if using the API module).
Host
api.host0.0.0.0AK_API__HOSTPort
api.port8000AK_API__PORTCustom Router Prefix
api.custom_router_prefix/customAK_API__CUSTOM_ROUTER_PREFIXEnabled Routes
api.enabled_routes.agentstrueAK_API__ENABLED_ROUTES__AGENTSEnabled
a2a.enabledfalseAK_A2A__ENABLEDAgents
a2a.agents["*"]["*"] for all)AK_A2A__AGENTS (comma-separated)URL
a2a.urlhttp://localhost:8000/a2aAK_A2A__URLTask Store Type
a2a.task_store_typein_memory, redisin_memoryAK_A2A__TASK_STORE_TYPEEnabled
mcp.enabledfalseAK_MCP__ENABLEDExpose Agents
mcp.expose_agentsfalseAK_MCP__EXPOSE_AGENTSAgents
mcp.agents["*"]AK_MCP__AGENTS (comma-separated)Stateless HTTP
mcp.stateless_httpfalseMcp-Session-Id)AK_MCP__STATELESS_HTTPEndpoint (not configurable)
/mcp on the main API server.http://{api.host}:{api.port}/mcp — use api.port / AK_API__PORT to change the port.Mounting AGUIRequestHandler (from agentkernel.agui, requires the agentkernel[agui] extra — pip install "agentkernel[agui]") is what enables the AG-UI protocol
surface; the agui block only parameterizes it, and it never switches the surface on by itself.
AGUIRequestHandler refuses to construct without an Authoriser or AuthValidator — AG-UI runs
agents on a caller's behalf and has no anonymous mode. Only agents whose runner declares
supports_streaming = True are reachable (currently OpenAI Agents SDK, LangGraph, Google ADK, and
Pydantic AI — not CrewAI or Smolagents). See examples/api/agui.
Agents
agui.agentsAK_AGUI__AGENTS (comma-separated)Prefix
agui.prefix/aguiAK_AGUI__PREFIXDefault Agent
agui.default_agentPOST {prefix}, in addition to POST {prefix}/{agent_name}); must be one of agui.agents when that list is setAK_AGUI__DEFAULT_AGENTState Tools
agui.state.enabledfalseget_agui_state / update_agui_state, giving agents read/write access to AG-UI's shared JSON state (a StateSnapshot is streamed back only when the state actually changed)AK_AGUI__STATE__ENABLEDagui.state.agentsAK_AGUI__STATE__AGENTS (comma-separated)Client Context Tools
agui.client_context.enabledfalseget_forwarded_props / get_agui_context tools over a run's forwardedProps and context fields; never injected into the prompt automaticallyAK_AGUI__CLIENT_CONTEXT__ENABLEDagui.client_context.agentsAK_AGUI__CLIENT_CONTEXT__AGENTS (comma-separated)Configure tracing and observability for monitoring agent execution.
Enabled
trace.enabledfalseAK_TRACE__ENABLEDType
trace.typelangfuse, openllmetry, logfire, cloudwatchlangfuseAK_TRACE__TYPELangfuse Setup:
To use Langfuse for tracing, install the langfuse extra:
pip install agentkernel[langfuse]
Configure Langfuse credentials via environment variables:
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
export LANGFUSE_HOST=https://cloud.langfuse.com # or your self-hosted instance
Enable tracing in your configuration:
trace:
enabled: true
type: langfuse
OpenLLMetry (Traceloop) Setup:
To use OpenLLMetry for tracing, install the openllmetry extra:
pip install agentkernel[openllmetry]
Configure Traceloop credentials via environment variables:
export TRACELOOP_API_KEY=your-api-key
export TRACELOOP_BASE_URL=https://api.traceloop.com # Optional: for self-hosted
Enable tracing in your configuration:
trace:
enabled: true
type: openllmetry
Pydantic Logfire Setup:
To use Logfire for tracing, install the logfire extra:
pip install agentkernel[logfire]
Configure the Logfire write token via an environment variable (optional — without a token, Logfire runs locally and does not ship traces):
export LOGFIRE_TOKEN=your-write-token
Enable tracing in your configuration:
trace:
enabled: true
type: logfire
AWS CloudWatch Setup:
To send traces to Amazon CloudWatch (via AWS X-Ray, searchable in Transaction Search), install the cloudwatch extra:
pip install agentkernel[cloudwatch]
Spans are exported over OTLP to the X-Ray endpoint of your region, signed with the standard AWS credential
chain (environment, profile, SSO, or instance/task role). Enable CloudWatch Transaction Search once in the
account, and give the agent's role the AWSXrayWriteOnlyAccess managed policy:
export AWS_REGION=us-east-1
# Optional: export through the CloudWatch agent or an OpenTelemetry collector instead
# export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces
Enable tracing in your configuration:
trace:
enabled: true
type: cloudwatch
Configure test comparison modes for automated testing. Test configuration is separate from the application configuration: it is not part of config.yaml. It lives in its own test-config.yaml file and is only loaded when the testing utilities (agentkernel.test) are used — see the Test Configuration (test-config.yaml) section for file resolution, environment variables, and migration notes.
Mode
modescore, llm, fallbackfallbackAK_TEST__MODEEvaluator
evaluatordeepevaldeepeval, opik or jev), or a dotted path to your own AKEvaluator subclassAK_TEST__EVALUATORLlm Model
llm.modelgpt-4o-miniAK_TEST__LLM__MODELLlm Provider
llm.provideropenaiAK_TEST__LLM__PROVIDERLlm Embedding Model
llm.embedding_modeltext-embedding-3-smallAK_TEST__LLM__EMBEDDING_MODELTest Modes:
score: Deterministic, offline string-match scoring via the configured evaluator (built-in deepeval: Scorer.quasi_exact_match_score; built-in opik: LevenshteinRatio, requires pip install "agentkernel[opik]"; built-in jev has no score mode)llm: LLM-as-judge evaluation via the configured evaluator (built-in deepeval or opik: GEval; built-in jev: a TypeSafe JEV yes/no Noul question) for semantic similarityfallback: Tries score first, falls back to llm if score fails# test-config.yaml (separate file — not config.yaml)
mode: fallback
evaluator: deepeval
llm:
model: gpt-4o-mini
provider: openai
embedding_model: text-embedding-3-small
Configure input and output guardrails to validate agent requests and responses for safety and compliance.
Input Guardrails
Enabled
guardrail.input.enabledfalseAK_GUARDRAIL__INPUT__ENABLEDType
guardrail.input.typeopenaiopenai, bedrock, walledaiAK_GUARDRAIL__INPUT__TYPEConfig Path
guardrail.input.config_pathNoneAK_GUARDRAIL__INPUT__CONFIG_PATHModel
guardrail.input.modelgpt-4o-miniAK_GUARDRAIL__INPUT__MODELID
guardrail.input.idNoneAK_GUARDRAIL__INPUT__IDVersion
guardrail.input.versionDRAFTAK_GUARDRAIL__INPUT__VERSIONOutput Guardrails
Enabled
guardrail.output.enabledfalseAK_GUARDRAIL__OUTPUT__ENABLEDType
guardrail.output.typeopenaiopenai, bedrock, walledaiAK_GUARDRAIL__OUTPUT__TYPEConfig Path
guardrail.output.config_pathNoneAK_GUARDRAIL__OUTPUT__CONFIG_PATHModel
guardrail.output.modelgpt-4o-miniAK_GUARDRAIL__OUTPUT__MODELID
guardrail.output.idNoneAK_GUARDRAIL__OUTPUT__IDVersion
guardrail.output.versionDRAFTAK_GUARDRAIL__OUTPUT__VERSIONGuardrail Setup:
To use OpenAI guardrails, install the openai-guardrails package:
pip install agentkernel[openai]
To use AWS Bedrock guardrails, install the AWS package:
pip install agentkernel[aws]
To use Walled AI guardrails, install the Walled AI package:
pip install agentkernel[walledai]
Create guardrail configuration:
For OpenAI: Create configuration files following the OpenAI Guardrails format.
For Bedrock: Create a guardrail in AWS Bedrock and note the guardrail ID and version.
For Walled AI: Set WALLED_API_KEY, use guardrail type walledai, and control PII masking with pii.
Configure guardrails in your configuration:
OpenAI Example:
guardrail:
input:
enabled: true
type: openai
model: gpt-4o-mini
config_path: /path/to/guardrails_input.json
output:
enabled: true
type: openai
model: gpt-4o-mini
config_path: /path/to/guardrails_output.json
Bedrock Example:
guardrail:
input:
enabled: true
type: bedrock
id: your-guardrail-id
version: "1" # or "DRAFT"
output:
enabled: true
type: bedrock
id: your-guardrail-id
version: "1"
Walled AI Example:
guardrail:
input:
enabled: true
type: walledai
pii: true
output:
enabled: true
type: walledai
pii: true
Enable the sandbox capability to let agents execute code and shell commands in an isolated,
permission-bounded environment. When enabled, agents automatically gain sandbox tools
(run_code, run_command, write_sandbox_file, read_sandbox_file, check_sandbox_task,
list_sandbox_sessions, new_sandbox_session, destroy_sandbox_session) and the usage
guidance is injected into their system prompt.
Minimal single-backend form (a default profile is synthesized from type + its config block):
sandbox:
enabled: true
type: local_subprocess # provider short name, or a dotted path to a SandboxProvider subclass
local_subprocess: {}
broker:
flavor: thread # thread (local default) | embedded
Full form with explicit workload profiles (provider + lifetime + policy + identity):
sandbox:
enabled: true
agents: [coder] # optional: attach tools/prompt only to these agents; omit = all
default_profile: workspace
principal_resolver: null # optional dotted path to a PrincipalResolver; null = agent identity
tool_output_max_chars: 8000
broker:
flavor: thread
wait_timeout: 60.0 # seconds before a sync wait promotes to a background task (0 = always)
profiles:
workspace:
type: docker # container-isolated; needs the sandbox-docker extra + a Docker daemon
scope: per_session # per_call | per_session | per_runtime
idle_timeout: 1800 # seconds of inactivity before the sandbox is reset on next touch
identity:
mode: agent # agent | user
policy:
network_egress: deny # allow | deny | allowlist
cpu: 1.0
memory_mb: 512
timeout: 30.0 # per-execution wall-clock seconds (always enforced)
strict: true # fail closed when the provider can't enforce a policy dimension
docker:
image: python:3.12-slim
Key fields:
enabled (AK_SANDBOX__ENABLED, default false) — master switch; inert when off.agents — agent names the tools/prompt attach to; omit for all agents.type (per profile) — local_subprocess (no isolation; dev/test), docker
(container isolation; sandbox-docker extra), e2b (managed micro-VMs; e2b extra),
daytona (cloud containers; daytona extra), ec2_ssm (attach to an existing EC2
instance via SSM; aws extra), or a dotted path to your own SandboxProvider.scope — per_call (fresh per execution), per_session (persists across turns),
per_runtime (one shared sandbox per profile).environment — managed (default; the provider creates and disposes sandboxes) or
attached (deliberately connect to an existing environment the framework never owns,
e.g. an EC2 instance via ec2_ssm; requires the provider's attach_to and is validated
against the provider's lifecycle capabilities at startup).policy — network egress, filesystem paths, cpu/memory, timeout; enforced per provider,
fail-closed under strict.identity.mode + principal_resolver — run code under the agent's or the invoking
user's identity.broker.flavor — thread (default, for CLI/REST) or embedded (inline/synchronous).See the Sandbox guide for the full
reference and the examples/sandbox and examples/sandbox/identity examples.
Configure integrations with messaging platforms.
Agent
slack.agent""AK_SLACK__AGENTAgent Acknowledgement
slack.agent_acknowledgement""AK_SLACK__AGENT_ACKNOWLEDGEMENTAgent
whatsapp.agent""AK_WHATSAPP__AGENTVerify Token, Access Token, App Secret, Phone Number ID, API Version
AK_WHATSAPP__VERIFY_TOKEN, AK_WHATSAPP__ACCESS_TOKEN, AK_WHATSAPP__APP_SECRET, AK_WHATSAPP__PHONE_NUMBER_ID, AK_WHATSAPP__API_VERSIONAgent
messenger.agent""AK_MESSENGER__AGENTVerify Token, Access Token, App Secret, API Version
AK_MESSENGER__VERIFY_TOKEN, AK_MESSENGER__ACCESS_TOKEN, AK_MESSENGER__APP_SECRET, AK_MESSENGER__API_VERSIONAgent
instagram.agent""AK_INSTAGRAM__AGENTInstagram Account ID, Verify Token, Access Token, App Secret, API Version
AK_INSTAGRAM__INSTAGRAM_ACCOUNT_ID, AK_INSTAGRAM__VERIFY_TOKEN, AK_INSTAGRAM__ACCESS_TOKEN, AK_INSTAGRAM__APP_SECRET, AK_INSTAGRAM__API_VERSIONAgent
telegram.agent""AK_TELEGRAM__AGENTBot Token, Webhook Secret, API Version
AK_TELEGRAM__BOT_TOKEN, AK_TELEGRAM__WEBHOOK_SECRET, AK_TELEGRAM__API_VERSIONAgent
teams.agent""AK_TEAMS__AGENTAgent Acknowledgement
teams.agent_acknowledgement""AK_TEAMS__AGENT_ACKNOWLEDGEMENTApp ID, App Password
AK_TEAMS__APP_ID, AK_TEAMS__APP_PASSWORDTenant ID
teams.tenant_id""AK_TEAMS__TENANT_IDAgent
gmail.agent"general"AK_GMAIL__AGENTClient ID, Client Secret, Token File, Poll Interval, Label Filter
AK_GMAIL__CLIENT_ID, AK_GMAIL__CLIENT_SECRET, AK_GMAIL__TOKEN_FILE, AK_GMAIL__POLL_INTERVAL, AK_GMAIL__LABEL_FILTERUse the AK_ prefix and underscores for nested fields:
export AK_DEBUG=true
export AK_SESSION__TYPE=redis
export AK_SESSION__REDIS__URL=redis://localhost:6379
export AK_SESSION__REDIS__TTL=604800
export AK_SESSION__REDIS__PREFIX=ak:sessions:
export AK_API__HOST=0.0.0.0
export AK_API__PORT=8000
export AK_A2A__ENABLED=true
export AK_MCP__ENABLED=false
export AK_TRACE__ENABLED=true
export AK_TRACE__TYPE=langfuse # or openllmetry, logfire, cloudwatch
# For Langfuse:
# export LANGFUSE_PUBLIC_KEY=pk-lf-...
# export LANGFUSE_SECRET_KEY=sk-lf-...
# export LANGFUSE_HOST=https://cloud.langfuse.com
# For OpenLLMetry:
# export TRACELOOP_API_KEY=your-api-key
# For Logfire:
# export LOGFIRE_TOKEN=your-write-token
# For CloudWatch:
# export AWS_REGION=us-east-1
# Test harness (loaded from the separate test-config.yaml — see Test Configuration)
export AK_TEST__MODE=fallback # Options: score, llm, fallback
export AK_TEST__EVALUATOR=deepeval # Built-in short name (deepeval, opik or jev), or a dotted path to your own AKEvaluator subclass
export AK_TEST__LLM__MODEL=gpt-4o-mini
export AK_TEST__LLM__PROVIDER=openai
export AK_TEST__LLM__EMBEDDING_MODEL=text-embedding-3-small
# Guardrails configuration
export AK_GUARDRAIL__INPUT__ENABLED=false
export AK_GUARDRAIL__INPUT__TYPE=openai
export AK_GUARDRAIL__INPUT__MODEL=gpt-4o-mini
export AK_GUARDRAIL__INPUT__CONFIG_PATH=/path/to/guardrails_input.json
export AK_GUARDRAIL__OUTPUT__ENABLED=false
export AK_GUARDRAIL__OUTPUT__TYPE=openai
export AK_GUARDRAIL__OUTPUT__MODEL=gpt-4o-mini
export AK_GUARDRAIL__OUTPUT__CONFIG_PATH=/path/to/guardrails_output.json
# Walled AI guardrails
export WALLED_API_KEY=your-walledai-api-key
export AK_GUARDRAIL__INPUT__PII=true
export AK_GUARDRAIL__OUTPUT__PII=true
export AK_DEBUG=true
# Messaging platforms (optional)
export AK_SLACK__AGENT=my-agent
export AK_WHATSAPP__AGENT=my-agent
export AK_MESSENGER__AGENT=my-agent
export AK_INSTAGRAM__AGENT=my-agent
export AK_TELEGRAM__AGENT=my-agent
export AK_GMAIL__AGENT=my-agent
export AK_GMAIL__CLIENT_ID=your-google-client-id
export AK_GMAIL__CLIENT_SECRET=your-google-client-secret
Create a .env file in your working directory:
AK_DEBUG=false
AK_SESSION__TYPE=redis
AK_SESSION__REDIS__URL=rediss://my-redis:6379
AK_SESSION__REDIS__TTL=1209600
AK_SESSION__REDIS__PREFIX=ak:prod:sessions:
AK_API__HOST=0.0.0.0
AK_API__PORT=8080
AK_A2A__ENABLED=true
AK_A2A__URL=http://localhost:8080/a2a
AK_TRACE__ENABLED=true
AK_TRACE__TYPE=langfuse # or openllmetry, logfire, cloudwatch
# Langfuse credentials (if using langfuse):
# LANGFUSE_PUBLIC_KEY=pk-lf-...
# LANGFUSE_SECRET_KEY=sk-lf-...
# LANGFUSE_HOST=https://cloud.langfuse.com
# OpenLLMetry credentials (if using openllmetry):
# TRACELOOP_API_KEY=your-api-key
# Logfire credentials (if using logfire):
# LOGFIRE_TOKEN=your-write-token
# CloudWatch region (if using cloudwatch; credentials come from the AWS credential chain):
# AWS_REGION=us-east-1
session:
type: redis
redis:
url: redis://localhost:6379
ttl: 604800
prefix: "ak:sessions:"
thread: # optional; configures Conversation Thread Support (enabled by mounting AgentThreadRequestHandler)
type: redis
redis:
url: redis://localhost:6379
ttl: 2592000
prefix: "ak:thread:"
execution:
mode: rest_sync
queues:
type: sqs # in_memory | sqs | kafka | nats, or a dotted path to a QueueTransport subclass — mandatory whenever this block is declared
input:
url: https://queue.example.com/<accountno>/<queuename> # sqs transport only
max_receive_count: 3
no_of_consumers: 5 # in-process pipeline + containerized deployments, ignored by serverless deployments
output:
url: https://queue.example.com/<accountno>/<queuename> # sqs transport only
max_receive_count: 3
no_of_consumers: 5 # in-process pipeline + containerized deployments, ignored by serverless deployments
# in_memory: {ack_wait: 300.0, dedup_window: 300.0} # in_memory transport settings, unused otherwise
# kafka: # kafka transport settings, unused otherwise
# bootstrap_servers: localhost:9092
# input_topic: agent-input
# output_topic: agent-output
# group_id: agent-kernel
# dlq_suffix: .dlq
# retry_backoff: 2.0
# delivery_timeout: 30.0
# metadata_timeout: 5.0
# client_config: {} # passthrough confluent-kafka producer/consumer settings (SASL, TLS, tuning)
# nats: # nats transport settings, unused otherwise
# url: nats://localhost:4222
# input_stream: AGENT_REQUESTS
# input_subject_prefix: chat.req
# output_stream: AGENT_REPLIES
# output_subject_prefix: chat.out
# partitions: 32
# ack_wait: 300.0
# retry_backoff: 2.0
# duplicate_window: 300.0
# max_age: 86400.0
# request_timeout: 10.0
# auto_provision: false # true for local/dev; leave false where NACK CRs own the objects
# batch_size is set by the deployment tooling — set via AK_EXECUTION__QUEUES__BATCH_SIZE, never here
response_store:
type: redis # in_memory | redis | valkey | dynamodb | dotted path — omit for the built-in in_memory store
retry_count: 5
delay: 5
redis: # if this is given, then valkey/dynamodb response store parts cannot be given
url: redis://localhost:6379
prefix: "ak:responses:"
ttl: 3600
valkey: # if this is given, then redis/dynamodb response store parts cannot be given (requires the `valkey` extra)
url: valkey://localhost:6379
prefix: "ak:responses:"
ttl: 3600
dynamodb: # if this is given, then redis/valkey response store parts cannot be given
table_name: table-name
table_arn: table-arn
ttl: 3600
api:
host: 0.0.0.0
port: 8000
enabled_routes:
agents: true
a2a:
enabled: true
agents: ["*"]
url: http://localhost:8000/a2a
task_store_type: in_memory
mcp:
enabled: false
expose_agents: false
agents: ["*"]
trace:
enabled: true
type: langfuse
# Note: test configuration is no longer set here — it lives in a separate
# test-config.yaml file (see the Test Configuration section)
guardrail:
input:
enabled: false
type: openai
pii: true
model: gpt-4o-mini
config_path: /path/to/guardrails_input.json
output:
enabled: false
type: openai
pii: true
model: gpt-4o-mini
config_path: /path/to/guardrails_output.json
# For Walled AI, set type: walledai, WALLED_API_KEY,
# and optionally use input/output pii (default: true) to enable/disable PII masking.
slack:
agent: my-agent
agent_acknowledgement: "Processing your request..."
whatsapp:
agent: my-agent
agent_acknowledgement: "Processing..."
messenger:
agent: my-agent
instagram:
agent: my-agent
telegram:
agent: my-agent
teams:
agent: my-agent
app_id: "<azure-app-client-id>"
app_password: "<azure-app-client-secret>"
gmail:
agent: my-agent
poll_interval: 30
label_filter: "INBOX"
{
"debug": false,
"session": {
"type": "redis",
"redis": {
"url": "redis://localhost:6379",
"ttl": 604800,
"prefix": "ak:sessions:"
}
},
"api": {
"host": "0.0.0.0",
"port": 8000,
"enabled_routes": {
"agents": true
}
},
"a2a": {
"enabled": true,
"agents": ["*"],
"url": "http://localhost:8000/a2a",
"task_store_type": "in_memory"
},
"mcp": {
"enabled": false,
"expose_agents": false,
"agents": ["*"]
},
"trace": {
"enabled": true,
"type": "langfuse"
},
"guardrail": {
"input": {
"enabled": false,
"type": "openai",
"model": "gpt-4o-mini",
"config_path": "/path/to/guardrails_input.json"
},
"output": {
"enabled": false,
"type": "openai",
"model": "gpt-4o-mini",
"config_path": "/path/to/guardrails_output.json"
}
},
"slack": {
"agent": "my-agent",
"agent_acknowledgement": "Processing your request..."
},
"whatsapp": {
"agent": "my-agent",
"agent_acknowledgement": "Processing..."
},
"messenger": {
"agent": "my-agent"
},
"instagram": {
"agent": "my-agent"
},
"telegram": {
"agent": "my-agent"
},
"teams": {
"agent": "my-agent",
"app_id": "<azure-app-client-id>",
"app_password": "<azure-app-client-secret>"
},
"gmail": {
"agent": "my-agent",
"poll_interval": 30,
"label_filter": "INBOX"
}
}
_) delimiter in environment variablesTest harness configuration (comparison mode, evaluator backend, llm models) is separate from the application configuration. It is not part of config.yaml — it lives in its own test-config.yaml file, resolved from the current working directory, and is only loaded when the testing utilities (agentkernel.test) are used. A legacy test: section in config.yaml is ignored. See Test Configuration under Configuration Options for the full list of fields and defaults.
The evaluator field accepts three built-in short names — deepeval (default, pip install "agentkernel[test]") or opik (pip install "agentkernel[opik]", Opik by Comet, runs entirely locally with OPIK_TRACK_DISABLE set so no Opik Cloud account or API key is needed) or jev (pip install "agentkernel[jev]", hosted TypeSafe JEV judge; mode: llm only, needs TYPESAFE_API_KEY, and sends the comparison text to api.typesafe.ai) — or a dotted path to your own AKEvaluator subclass.
test-config.yaml:
mode: fallback
evaluator: deepeval
llm:
model: gpt-4o-mini
provider: openai
embedding_model: text-embedding-3-small
Note that the file is un-nested — there is no top-level test: key. If the file is missing, defaults apply silently (score and fallback tests need no configuration file at all).
Override the test config file path:
export AK_TEST_CONFIG_PATH_OVERRIDE=/path/to/test-config.yaml
Environment variables use the AK_TEST__ prefix and override test-config.yaml values:
export AK_TEST__MODE=fallback # Options: score, llm, fallback
export AK_TEST__EVALUATOR=deepeval
export AK_TEST__LLM__MODEL=gpt-4o-mini
export AK_TEST__LLM__PROVIDER=openai
export AK_TEST__LLM__EMBEDDING_MODEL=text-embedding-3-small
To add support for a new framework:
Runner class for your frameworkAgent wrapper classModule class that registers agents with the RuntimeExample structure:
from agentkernel.core import Agent, Runner, Module
class MyFrameworkRunner(Runner):
def run(self, agent, prompt, session):
# Implement framework-specific execution
pass
class MyFrameworkAgent(Agent):
def __init__(self, native_agent):
self.native_agent = native_agent
self.runner = MyFrameworkRunner()
class MyFrameworkModule(Module):
def __init__(self, agents):
super().__init__()
for agent in agents:
wrapped = MyFrameworkAgent(agent)
self.register(wrapped)
Sessions maintain state across agent interactions. Framework adapters manage their own session storage within the Session object using namespaced keys:
"crewai" — CrewAI session data"langgraph" — LangGraph session data"openai" — OpenAI Agents SDK session data"adk" — Google ADK session data"pydanticai" — Pydantic AI session data (message history)Access the session in your runner:
def run(self, agent, prompt, session):
# Get framework-specific data
my_data = session.get("my_framework", {})
# Process and update data
my_data["last_prompt"] = prompt
# Update session
session.set("my_framework", my_data)
Requirements:
Setup:
git clone https://github.com/yaalalabs/agent-kernel.git
cd agent-kernel/ak-py
uv sync # or: pip install -e ".[dev]"
Run Tests:
uv run pytest
# or: pytest
Code Quality:
The project uses:
black — Code formattingisort — Import sortingmypy — Type checkingUnless otherwise specified, all content, including all source code files and documentation files in this repository are:
Copyright (c) 2025-2026 Yaala Labs.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
Contributions are welcome! Please feel free to submit a Pull Request.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.9.5 | 9 Oct 2026 | 75 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 22:31 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:ce4af2ee615f11b2e4fbdcd392e711d90d511902ce0d00015a7190c45cf9b5dc