Skip to content

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:

@kedi.bind(file="summarize.kedi")
def summarize(text: str) -> str:
    ...

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.configure(
    adapter="pydantic",
    model="openai:gpt-4o-mini",
    system="Answer with evidence.",
)

kedi.context(...) temporarily merges overrides:

with kedi.context(model="openai:gpt-4.1"):
    result = summarize("...")

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:

with kedi.parallel(max_workers=4):
    result = summarize("...")

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:

from kedi.lang import compile_program, parse_program

Executor protocols and the default implementation are also re-exported from kedi; specialized engine and playground executor classes live in their respective submodules.