KsADK

Runtime Architecture

KsADK local runtime has one central job: load a user agent project, adapt the selected framework to a common runner interface, and expose predictable local protocols for terminal, browser, and API clients.

Layer Model

KsADK request lifecycle

Entry → Boot → HTTP/UI → Conversations Runtime → Runner → Session persistence → 0.6.7 Run capability layer. The important boundary is that the HTTP server and conversation runtime do not need to know whether the user project is ADK, LangGraph, LangChain, or DeepAgents. They call BaseRunner.invoke() or BaseRunner.stream().

Core Packages

PackageResponsibility
ksadk.clicommand entry points, local process setup, user-facing errors
ksadk.detectionproject config, entry file, framework, and agent variable detection
ksadk.runnerscommon runner contract and framework adapters
ksadk.serverFastAPI app, local Web UI APIs, OpenAI-compatible endpoints
ksadk.conversationsmessage normalization, session turn orchestration, protocol payloads
ksadk.sessionslocal and pluggable session storage
ksadk_runtime_common.workspace_filesreusable workspace file routes and preview security

Startup Lifecycle

agentengine run and agentengine web follow the same broad path:

  1. resolve the project directory.
  2. re-execute inside the project virtual environment when needed.
  3. load environment and project settings.
  4. detect the framework and entry point.
  5. create the matching runner.
  6. load the user agent.
  7. run terminal mode or start the local HTTP server.

If framework detection returns unknown, the CLI stops before importing the user project as a runner.

KsADK startup lifecycle

Startup Boundaries

The local runtime has a strict startup boundary:

  1. CLI code resolves paths, configuration, environment variables, and the project virtual environment.
  2. detection code decides which framework adapter should be used.
  3. the runner factory creates a framework-specific runner.
  4. the runner loads user code.
  5. the server layer exposes HTTP protocols and delegates execution to the runner.

Detection happens before user code is imported. That distinction is important for safety and debuggability: a broken module import should be reported as an agent loading problem, while a missing agentengine.yaml, invalid entry point, or unsupported framework should be reported as a project detection problem.

For public examples, keep project setup explicit:

agentengine.yaml
name: support-agent
framework: langgraph
entry_point: agent.py
agent_variable: root_agent

Explicit configuration reduces ambiguity in CI and makes the same project work the same way under agentengine run, agentengine web, local API tests, and packaging checks.

Framework Detection

Detection uses explicit configuration first, then convention:

Framework detection flow

Public samples should include agentengine.yaml because explicit config is easier to review and less dependent on source-code heuristics.

The convention-based fallback is still useful for quick experiments. It checks common project layouts such as:

  • a root agent.py, main.py, or app.py.
  • a package directory with agent.py, main.py, app.py, or __init__.py.
  • a src/<package> layout.
  • langgraph.json graph targets.

When convention detection is used, the runtime still needs two concrete facts: which file should be imported and which variable inside that file is the agent object. If either value is ambiguous, add agentengine.yaml instead of relying on heuristics.

Runner Contract

Every runner implements the same conceptual contract:

MethodMeaning
load_agent()import and prepare the user agent object
invoke(input_data)execute one non-streaming turn
stream(input_data)execute one streaming turn
prepare_for_request(model)apply per-request model override where supported
close()release resources when the server shuts down

This contract is intentionally narrow. Framework-specific behavior belongs in the adapter, not in the FastAPI endpoint.

The narrow contract also defines where custom behavior should live:

NeedPreferred location
custom state mapping for LangGraphksadk_prepare_state in the user module
custom input mapping for LangChainksadk_prepare_input in the user module
model override handlingrunner prepare_for_request()
framework-native session continuityrunner session adapter
protocol-specific JSON/SSE formattingserver and conversation runtime

If you are adding a new framework adapter, start with BaseRunner and implement load_agent(), invoke(), and stream() first. Add session continuity, dynamic model overrides, or protocol-specific event mapping only after the basic invoke and stream paths are stable.

Request Lifecycle

A normal non-streaming /v1/responses request follows this path:

Streaming uses the same preparation path, then serializes internal semantic events into server-sent events. Text deltas, reasoning, tool calls, tool results, approval interrupts, final output, and errors are represented as runtime events before they become protocol-specific SSE payloads.

Streaming Event Model

Streaming output is normalized before it is serialized. Framework adapters may emit very different native events, but the conversation runtime expects a small set of semantic chunk types:

Chunk typeMeaningTypical source
textassistant text deltamodel token stream
thinkingreasoning or thought delta when availableprovider or ADK event
tool_calltool call started or arguments updatedLangGraph, ADK, MCP, or custom tool event
tool_resulttool output became availableframework tool result event
interruptrun paused for approval or external inputgraph interrupt or approval flow
finalfinal authoritative outputframework final state
errorexecution failedrunner or protocol exception

The protocol layer then maps those semantic events to /v1/responses, /v1/chat/completions, /run_sse, or the local Web UI action format. This is why application code should not depend on a specific SSE event name unless it is writing a client for that exact public protocol.

Model Policy And Thinking Semantics

Whether a thinking chunk appears, and how reasoning content is injected, is decided by the runtime's unified model policy and thinking-disable injection semantics (unified from 0.6.6, disable injection completed in 0.6.7):

  • Unified model policy: hosted deployments inject primary / multimodal / fallback defaults through AGENTENGINE_MODEL_POLICY_JSON, shared by Hermes, OpenClaw, and generic agents. Explicit request parameters or explicit environment variables still take precedence over policy defaults.
  • Fallback retry: the conversation runtime automatically retries once with the fallback model on recoverable errors such as timeouts, rate limiting, 5xx, model unavailability, or permission/quota errors. 400 parameter errors, business errors, and tool errors are not swallowed. When fallback triggers, the next streaming turn may switch to the fallback backend, and whether a thinking chunk appears depends on the target model's capability.
  • Thinking-disable injection: when model_options.thinking is disabled (reasoning.effort=none, thinking.type=disabled, or max_reasoning_tokens<=0), the runtime automatically injects enable_thinking=false and chat_template_kwargs.enable_thinking=false into extra_body (compatible with DeepSeek-style models) and filters reasoning output items from the stream, so no thinking chunk is emitted over SSE.

For the policy JSON structure, catalog fields, and injection details see Environment Variables.

Session And Context Boundary

Every turn builds a PlatformInvocationContext before calling the runner. It contains the stable identifiers and runtime facts a framework adapter may need:

  • agent_id, user_id, session_id, and invocation metadata.
  • normalized input content and message history.
  • effective attachments and current-turn attachments.
  • model, model metadata, and model options.
  • knowledge and memory context when those integrations are enabled.

The runner receives this context as part of the prepared input. Business logic should prefer the documented runner payload fields and framework hooks over reading private server globals. That keeps local terminal runs, Web UI runs, and OpenAI-compatible API calls aligned.

Checkpoint, Resume, And Cooperative Cancel

Added in 0.6.7

KsADK introduces a framework-level checkpoint/resume capability layer and completes CancelRun cooperative cancellation.

Run-level checkpoint, resume, and cancel sit on top of the session store and framework checkpoint backend, as a capability layer independent of streaming chunks. The conversation runtime writes a run_status event on every turn and exposes recovery and cancel entry points at checkpoint boundaries:

CapabilityMeaningTrigger
checkpoint writepersists a resumable snapshot at a turn boundaryrunner writes it on turn completion or interrupt
resumeresumes a run from a checkpointPOST /agentengine/api/v1/ResumeRun
previewpreviews resume content and impactPOST /agentengine/api/v1/GetCheckpointResumePreview
listlists checkpoints under a sessionPOST /agentengine/api/v1/ListSessionCheckpoints
cooperative cancelrequests an in-flight run to stopPOST /agentengine/api/v1/CancelRun

CancelRun is a cooperative cancel: the runtime observes the cancel request at the next runner cooperation point (for example the next streaming chunk, a tool call boundary, or an interrupt checkpoint), stops the run, writes run_status=cancelled, and preserves already-produced checkpoints and events for later resume where possible. It does not hard-kill the process or discard already-persisted turns.

Resume capability is gated by both RuntimeCapabilities.ResumeRun.ResumeMode and RunLifecycle returned from GetAgentUiBootstrap (time_travel / forward_only / none); the frontend entry point must satisfy both RunLifecycle.Checkpoints and RunLifecycle.CheckpointResume before being shown.

For the full action paths, ResumeMode semantics, SubscribeRunEvents replay, and the 5-minute server protection timeout see Sessions And Files.

Local Protocol Entrypoints

EndpointPurpose
POST /v1/responsespreferred OpenAI-compatible local protocol
POST /v1/chat/completionscompatibility with Chat Completions clients
POST /agentengine/api/v1/RunAgentlocal Web UI action-style protocol
POST /run_sseADK Web compatible local execution path
POST /agentengine/api/v1/UploadFilelocal file upload for UI flows
/_ksadk/workspace/v1/*workspace file list/read/write/delete routes

External clients should prefer /v1/responses unless they are integrating with the local Web UI itself.

Public Documentation Boundary

This page describes the public local runtime architecture. It intentionally does not publish private gateway behavior, internal cluster deployment details, internal kubeconfig paths, private registry names, or customer-specific runbooks.

On this page