Your first tool
Everything in KAOS is built on kaos-core — a dependency-light runtime and an
MCP-native tool model. A tool is a typed unit of work: you write an async
function, decorate it, register it on a KaosRuntime, and execute it. The runtime
derives the tool’s input schema from your type hints, so the same tool is callable
from Python and from any MCP client.
This runs fully offline — no API key, no network.
Run it
Section titled “Run it”uv run examples/first-tool.pyword count: 5The code
Section titled “The code”#!/usr/bin/env -S uv run --script# /// script# requires-python = ">=3.13"# dependencies = ["kaos-core>=0.1.4,<0.2"]# ///"""Author, register, and execute your first KAOS tool.
`kaos-core` is the dependency-light runtime every other package builds on.A *tool* is a typed, MCP-native unit of work: you write an async function,decorate it with `@kaos_tool`, register it on a `KaosRuntime`, and executeit. The runtime derives the input schema from your type hints.
Fully offline and deterministic — no key, no network.
Run it:
uv run examples/first-tool.py"""
from __future__ import annotations
import asyncio
from kaos_core import ( KaosRuntime, ToolAnnotations, ToolCapability, ToolCategory, kaos_tool,)
@kaos_tool( name="kaos-learn-wordcount", description="Count the words in a piece of text.", category=ToolCategory.DATA, capability=ToolCapability.ANALYZE, # readOnly + idempotent: safe to call anytime; an agent may auto-allow it. annotations=ToolAnnotations(readOnlyHint=True, idempotentHint=True), auto_register=False,)async def word_count(text: str) -> int: return len(text.split())
async def main() -> str: runtime = KaosRuntime() runtime.tools.register_tool(word_count)
tool = runtime.tools.get_tool("kaos-learn-wordcount") result = await tool.execute({"text": "the quick brown fox jumps"})
# ToolResult wraps the return value; `.text` is the rendered output. print(f"word count: {result.text}") return result.text
if __name__ == "__main__": out = asyncio.run(main()) assert out == "5", f"expected 5, got {out!r}"What to notice
Section titled “What to notice”@kaos_toolturns a plain async function into a registered tool.categoryandcapabilityclassify it;annotationsdescribe its safety (areadOnlyHinttool is safe for an agent to call without asking).- The schema is derived from type hints.
word_count(text: str) -> intmeans the tool accepts{"text": str}— you never hand-write JSON schema. KaosRuntimeis the container you register tools on and execute them through. It’s the same runtime agents and MCP servers use.ToolResultwraps every result..textis the rendered output; structured results and resource links are also available.
You have a runtime and a tool. Next, build the data structure KAOS tools mostly operate on.
Build a document → The Block/Inline AST that every KAOS extractor produces and every tool operates on.