Core agent framework for the k agent framework
Project description
kagent
Core agent runtime for the K agent framework — a context-first, three-level agent SDK built on kai.
Key Principles
- Context-first — Context construction is managed by
ContextBuilder— a protocol with built-in implementations for common patterns. You control exactly what goes to the LLM. - Three levels —
agent_step()→agent_loop()→Agent. Pick the level that fits. - No framework concepts — Callbacks are plain function parameters. No Hooks, no Middleware.
- Unified tools — Uses
kai.Tooldirectly. Define innerParams(BaseModel)for typed, auto-schema tools. - kai-native — Uses
kai.Message,kai.Context,kai.Provider,kai.StreamEventdirectly. - App-owned provider assembly —
kagentconsumes a concretekai.Provider; provider factory/registry concerns stay in the application layer.
Architecture
┌──────────────────────────────────────────────────────┐
│ Application (kcode, custom agent) │
│ ┌────────────────────────────────────────────────┐ │
│ │ Level 2: Agent (stateful SDK) │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ Level 1: agent_loop() (multi-turn) │ │ │
│ │ │ ┌────────────────────────────────────┐ │ │ │
│ │ │ │ Level 0: agent_step() (one turn) │ │ │ │
│ │ │ │ ┌──────────────────────────────┐ │ │ │ │
│ │ │ │ │ kai.stream() (LLM call) │ │ │ │ │
│ │ │ │ └──────────────────────────────┘ │ │ │ │
│ │ │ └────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
| Level | Function | Context control | Use case |
|---|---|---|---|
| 0 | agent_step() |
Caller builds kai.Context |
Full control, custom loops |
| 1 | agent_loop() |
context_builder param |
Standard multi-turn agent |
| 2 | Agent |
Auto-managed + callbacks | Stateful SDK, interactive apps |
Quick Start
Define a Tool
Subclass kai.Tool, define inner Params(BaseModel), and override execute():
from pydantic import BaseModel, Field
from kai import Tool, ToolResult
class GetWeather(Tool):
name: str = "get_weather"
description: str = "Get weather for a location."
class Params(BaseModel):
location: str = Field(description="City name")
async def execute(self, params: GetWeather.Params) -> ToolResult:
return ToolResult(output=f"Sunny in {params.location}")
JSON Schema is auto-generated from the Params model — no manual parameters dict needed.
Level 2: Agent (recommended)
The simplest way to use kagent — stateful, multi-turn, streaming or one-shot:
from kagent import Agent
agent = Agent(
provider=my_provider,
system="You are a helpful assistant.",
tools=[GetWeather()],
)
# One-shot
msg = await agent.complete("What's the weather in Tokyo?")
print(msg.extract_text())
# Streaming
async for event in agent.run("What's the weather in Paris?"):
match event:
case TurnEnd(message=msg):
print(msg.extract_text())
# Multi-turn (state persists)
await agent.complete("Remember: my name is Alice.")
msg = await agent.complete("What's my name?") # "Alice"
Level 1: agent_loop()
For more control — you own the state, customize context via callbacks:
from kagent import AgentState, agent_loop, TurnEnd
state = AgentState(
system="You are helpful.",
messages=[Message(role="user", content="What's the weather?")],
tools=[GetWeather()],
)
async for event in agent_loop(provider=my_provider, state=state):
match event:
case TurnEnd(message=msg):
print(msg.extract_text())
# state.messages is mutated in-place with the full conversation
Context customization via context_builder:
from kagent import SlidingWindowBuilder
# Built-in: sliding window
async for event in agent_loop(
provider=p, state=state,
context_builder=SlidingWindowBuilder(window_size=20),
):
...
# Custom: implement the ContextBuilder protocol
class MyBuilder:
async def build(self, state: AgentState) -> Context:
return Context(
system=f"{state.system}\nTime: {datetime.now()}",
messages=state.messages[-20:],
tools=state.tools,
)
async for event in agent_loop(provider=p, state=state, context_builder=MyBuilder()):
...
Level 0: agent_step()
Full control — you build the kai.Context, manage state yourself:
from kagent import agent_step, TurnEnd
context = Context(
system="You are helpful.",
messages=[Message(role="user", content="Hello!")],
tools=my_tools,
)
async for event in agent_step(provider=provider, context=context, tools=my_tools):
match event:
case TurnEnd(message=msg):
print(msg.extract_text())
Callbacks
All callbacks are plain async functions passed as kwargs — same at Level 1 and Level 2:
| Callback | Signature | Purpose |
|---|---|---|
context_builder |
ContextBuilder protocol |
Control what goes to the LLM |
on_tool_result |
(call_id, tool_name, ToolResult) -> ToolResult |
Intercept/modify tool results |
should_continue |
(AgentState, Message) -> bool |
Custom loop termination |
Interactive Control (Level 2 only)
agent.steer(Message(role="user", content="Focus on X instead.")) # interrupt current run
agent.follow_up(Message(role="user", content="Now do Y.")) # queue after current run
agent.abort() # cancel current run
More
See docs/arch.md for detailed architecture, algorithm pseudo-code, context flow, and design comparisons.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kcastle_agent-0.0.1a2.tar.gz.
File metadata
- Download URL: kcastle_agent-0.0.1a2.tar.gz
- Upload date:
- Size: 24.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c2d8e81c85129122528d518fd1c6b6b24d33a4166a33df504cd3f43209eb38e
|
|
| MD5 |
e627fee086af3741d54c18c05ed87b74
|
|
| BLAKE2b-256 |
c33779e98796ec8068c6323d76708a561f60ff7a31846cdebe868276621df8c8
|
Provenance
The following attestation bundles were made for kcastle_agent-0.0.1a2.tar.gz:
Publisher:
release.yml on shenxiangzhuang/kcastle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kcastle_agent-0.0.1a2.tar.gz -
Subject digest:
8c2d8e81c85129122528d518fd1c6b6b24d33a4166a33df504cd3f43209eb38e - Sigstore transparency entry: 1183046292
- Sigstore integration time:
-
Permalink:
shenxiangzhuang/kcastle@b06efe81823098fa16b6388a351240ef50be484c -
Branch / Tag:
refs/tags/v0.0.1a2 - Owner: https://github.com/shenxiangzhuang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b06efe81823098fa16b6388a351240ef50be484c -
Trigger Event:
release
-
Statement type:
File details
Details for the file kcastle_agent-0.0.1a2-py3-none-any.whl.
File metadata
- Download URL: kcastle_agent-0.0.1a2-py3-none-any.whl
- Upload date:
- Size: 31.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e705794a5498cc3bc2021f6fabff83bfa36602b0c8ebc5dad21c0a32cd2734ef
|
|
| MD5 |
7d564d2c5d696f8f43fd89dbfeaaba0c
|
|
| BLAKE2b-256 |
1a32623fb45e640fa4196439bf72bfa6a02ebb379ffc47caef4b41b8b22db776
|
Provenance
The following attestation bundles were made for kcastle_agent-0.0.1a2-py3-none-any.whl:
Publisher:
release.yml on shenxiangzhuang/kcastle
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kcastle_agent-0.0.1a2-py3-none-any.whl -
Subject digest:
e705794a5498cc3bc2021f6fabff83bfa36602b0c8ebc5dad21c0a32cd2734ef - Sigstore transparency entry: 1183046319
- Sigstore integration time:
-
Permalink:
shenxiangzhuang/kcastle@b06efe81823098fa16b6388a351240ef50be484c -
Branch / Tag:
refs/tags/v0.0.1a2 - Owner: https://github.com/shenxiangzhuang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b06efe81823098fa16b6388a351240ef50be484c -
Trigger Event:
release
-
Statement type: