Python API¶
The Python API embeds Kedi programs in typed Python callables. It preserves the
same template, substitution, output, profile, tool, MCP, approval, skills,
artifact, conversation, and runtime semantics as .kedi files.
Embed Kedi in Python¶
Use @kedi.query for a short program in a docstring:
import kedi
@kedi.query
def summarize(text: str) -> str:
"""kedi
>> One-sentence summary of <text>: [summary: str].
= `summary`
"""
...
print(summarize("Kedi combines LLM templates with Python."))
Use @kedi.bind when the implementation belongs in a separate .kedi file:
In both forms, Python owns the callable signature and Kedi owns execution. The stub body is never called.
Decorator-Based Programs¶
The API exposes four decorators:
| Decorator | Role |
|---|---|
@kedi.query |
Compile a Kedi procedure body from the function docstring |
@kedi.bind(file=...) |
Run a complete file-backed Kedi program |
@kedi.type |
Register a Python class for Kedi type resolution |
@kedi.tool |
Add tool metadata and optional retry behavior to a callable |
@kedi.approval registers a default dynamic approval handler in the current
Python API context.
Global and Scoped Configuration¶
kedi.configure(...) replaces process-context defaults for subsequent calls:
kedi.context(...) temporarily merges overrides:
Use async with in asynchronous code. Configuration is held in a
ContextVar, so scoped overrides follow async task context rather than a
single mutable process-global stack.
Registered Types and Tools¶
from pydantic import BaseModel
@kedi.type
class Finding(BaseModel):
severity: str
message: str
@kedi.tool(risk="read_only")
def search_docs(query: str) -> list[str]:
"""Search the local documentation index."""
return []
Registering a tool makes it available to the runtime environment. The Kedi
program must still opt into it with > use: search_docs.
Runtime Control¶
Independent template calls are sequential by default:
kedi.cache_info() and kedi.clear_cache() inspect and clear the in-memory
parse and response caches. kedi.force(value) explicitly resolves a low-level
KediPromise; ordinary query results are resolved before they return.
kedi.session() creates an explicit stateful boundary for model history and
artifact ownership. Artifact handling is enabled by default and can be
configured or disabled through artifacts= on contexts and decorators.
kedi.interactive() creates a persistent process-local runtime for executing
complete Kedi fragments without replaying earlier fragments:
with kedi.interactive() as interactive_session:
interactive_session.execute("[value: int] = `40`")
assert interactive_session.execute("= `value + 2`") == 42
See Interactive Execution for source identity, lifecycle, failure behavior, and terminal REPL usage.
Public API Map¶
Common imports come from the package root:
from kedi import (
ApprovalDecision,
ApprovalPolicy,
ApprovalRequest,
AgentMessageEvent,
AgentRunStateEvent,
AgentStreamEvent,
ArtifactChunk,
ArtifactHandle,
ArtifactPolicy,
ArtifactRef,
ArtifactReleaseResult,
ArtifactSearchResult,
AsyncAgentEventQueue,
CacheInfo,
ConversationState,
InteractiveSession,
KediPromise,
KediPromiseLeak,
KediRuntime,
McpServerSpec,
bind,
cache_info,
clear_cache,
configure,
context,
force,
interactive,
observe_agent_events,
parallel,
query,
reset_config,
session,
tool,
type,
)
observe_agent_events(...) provides adapter-neutral, completed commentary and
final messages as a non-authoritative side channel. See
Stream Events for callback and async
queue examples, event ordering, and failure semantics.
Compiler entry points are in kedi.lang:
Executor protocols and the default implementation are also re-exported from
kedi; specialized engine and playground executor classes live in their
respective submodules.