Skip to main content

Core agent framework for the k agent framework

Project description

kagent

PyPI

Core agent runtime for the K agent framework — a context-first, three-level agent SDK built on kai.

Key Principles

  1. 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.
  2. Three levelsagent_step()agent_loop()Agent. Pick the level that fits.
  3. No framework concepts — Callbacks are plain function parameters. No Hooks, no Middleware.
  4. Unified tools — Uses kai.Tool directly. Define inner Params(BaseModel) for typed, auto-schema tools.
  5. kai-native — Uses kai.Message, kai.Context, kai.Provider, kai.StreamEvent directly.
  6. App-owned provider assemblykagent consumes a concrete kai.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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kcastle_agent-0.0.1a1.tar.gz (24.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kcastle_agent-0.0.1a1-py3-none-any.whl (31.2 kB view details)

Uploaded Python 3

File details

Details for the file kcastle_agent-0.0.1a1.tar.gz.

File metadata

  • Download URL: kcastle_agent-0.0.1a1.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

Hashes for kcastle_agent-0.0.1a1.tar.gz
Algorithm Hash digest
SHA256 5d1580eb538e13a1f0ff55cd65dd6759e6aa8693cb4a6516a4d9d33696bc8de5
MD5 b2b416acfb606e66a4d0d7a419fbb0ae
BLAKE2b-256 3183ebf170abc59003b9bb69ff1f48e176bfa975c1f529f8ba94cbaf60b5d1e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for kcastle_agent-0.0.1a1.tar.gz:

Publisher: release.yml on shenxiangzhuang/kcastle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kcastle_agent-0.0.1a1-py3-none-any.whl.

File metadata

File hashes

Hashes for kcastle_agent-0.0.1a1-py3-none-any.whl
Algorithm Hash digest
SHA256 98e17a57fb01d4f61a67946a13acee1c2f3ad3917bded23d2c38abfe8168f52a
MD5 e4df5a9fac5cc8212c97c1fbf3e8b9ae
BLAKE2b-256 fe21c9609512ab36143106602f751c0939f9ba761cae4d5d4d49842072d299b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for kcastle_agent-0.0.1a1-py3-none-any.whl:

Publisher: release.yml on shenxiangzhuang/kcastle

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page