Skip to main content
Version: Next

Execution Flow

How requests flow through Agent Kernel from user input to agent response: synchronously, streamed, or through queues.

Request Lifecycle

Every execution surface converges on the same core pipeline: ChatService/AgentServiceRuntime.run() (or Runtime.stream()) → pre-hooks → Runner → framework → post-hooks → session persistence.

Detailed Flow

1. Request Reception

The request enters through one of the execution surfaces:

  • CLI: interactive terminal input
  • REST API: HTTP POST /api/v1/chat (JSON) or POST /api/v1/chat-multipart (file uploads)
  • AWS Lambda: API Gateway event routed by the Lambda handler
  • SQS queue: in queue mode, a request message consumed by the agent-runner Lambda or ECS consumer threads
  • WebSocket: a message on the configured chat route via AWS API Gateway WebSocket (async/stream modes)
  • MCP/A2A: protocol-specific request against the mounted /mcp or /a2a routes
  • Messaging platforms: webhook events from Slack, WhatsApp, Messenger, Instagram, Telegram, Teams, or Gmail

2. Request Building and Agent Resolution

ChatService validates the payload and builds a list of typed requests (AgentRequestText, AgentRequestImage, AgentRequestFile, plus AgentRequestAny entries for any additional context fields). It then selects the agent and session through AgentService:

from agentkernel.core.service import AgentService

service = AgentService()
service.select(name="assistant", session_id="user-123") # loads or creates the session

Under the hood the agent registry lives on the runtime:

from agentkernel.core import Runtime

runtime = Runtime.current()
agent = runtime.agents().get("assistant")
session = runtime.sessions().get("user-123") or runtime.sessions().new("user-123")

If conversation threads are enabled, user_id is required and the thread manager records the user message (and stores any attachments) before the run.

3. Agent Execution

Runtime.run() acquires the session lock, runs the hook pipeline, and delegates to the framework-specific runner:

reply = await runtime.run(agent, session, requests)
  1. Session lock: async with session serializes concurrent requests per session and makes Session.current() available.
  2. Pre-hooks: agent hooks first, then system hooks (input guardrails, multimodal preprocessing). A pre-hook may rewrite the request list or halt by returning an AgentReply.
  3. Runner.run(): converts requests to the framework's native format, restores framework session state, executes, and converts the result back to an AgentReply (AgentReplyText, AgentReplyImage, or AgentReplyAny for structured output).
  4. Post-hooks: system hooks (output guardrails) first, then agent hooks.
  5. Persistence: the session store saves the session; the volatile cache is cleared in a finally block.

4. Response Return

The reply travels back through the surface it arrived on: JSON body for REST, Lambda response for API Gateway, a message on the output queue in queue mode, or a WebSocket push. Thread-enabled deployments also append the assistant reply to the conversation thread.

Synchronous Flow (Sequence)

Streaming Flow (execution.mode: stream)

With execution.mode: stream, the REST API switches POST /api/v1/chat (and /chat-multipart) to a Server-Sent Events response, driven by Runtime.stream():

  • If a pre-hook halts (e.g., an input guardrail trips), the stream yields a single StreamChunk with error set and done: true.
  • Framework support: OpenAI Agents SDK, LangGraph, and Google ADK stream natively. CrewAI and Smolagents raise NotImplementedError in stream mode.
  • On AWS serverless, the same StreamChunks are delivered as WebSocket STREAM_CHUNK messages instead of SSE; see below.

Queue-Based Flow (AWS)

In queue mode (execution.queues.* configured), the HTTP request and the agent execution are decoupled by SQS FIFO queues. This is the recommended production topology on AWS for both Lambda and ECS:

  • rest_sync holds the HTTP connection and polls the response store server-side; rest_async returns a request_id immediately for the client to poll.
  • FIFO queues use MessageGroupId = session_id (per-session ordering) and deduplication IDs; failed messages are retried after the visibility timeout, and dead-letter queues catch messages exceeding max_receive_count.
  • See the Queue Mode Guide for retry/DLQ details and ECS threading internals.

WebSocket Flow (AWS Serverless)

In async and stream modes, clients hold a WebSocket connection to API Gateway. Connection IDs are recorded in DynamoDB by a connection-handler Lambda, and replies are pushed back through the still-open socket:

See AWS Serverless Deployment for configuration, authentication, and Terraform wiring.

Mode Selection Cheat Sheet

execution.modeTransportReply deliveryQueuesResponse storeAvailable on
(unset) / defaultHTTPJSON on the same connection--Everywhere RESTAPI/CLI runs
rest_syncHTTPJSON on the same connection (server polls store)RequiredRequiredAWS Lambda, AWS ECS
rest_asyncHTTPClient polls with request_idRequiredRequiredAWS Lambda, AWS ECS
asyncWebSocketSingle CHAT_RESPONSE pushOptionalNot usedAWS Lambda
streamSSE (REST) or WebSocket (AWS serverless)Token-level StreamChunksOptional (WebSocket path)Not usedREST API surfaces; AWS Lambda WebSocket

Multimodal Flow

When multimodal support is enabled and a request carries images or files, the system pre-hook transforms the request before the agent sees it:

The agent's conversation history stays free of binary data; the auto-registered analyze_attachments tool retrieves stored attachments on demand. See Multimodal.

Ready to Ship Your
First Agent?

Free, open-source, Apache 2.0. No licensing costs, no vendor lock-in. Join hundreds of developers building production AI agents with Agent Kernel.

Agent Kernel
Ask Agent Kernel