Python API Reference¶
All stable high-level names below are imported from kedi.
Use the public export inventory for all root
exports and the parameter reference for
the exact configuration surfaces. Examples with ... below are signature
sketches, not executable programs.
Public Selection Types¶
FrameworkAdapterNameisLiteral["pydantic", "dspy", "langchain"].AgentNameisLiteral["claude", "codex", "acp"].AdapterLikeisAgentAdapter[Any] | LazyAdapter.ApprovalModeisLiteral["allow", "deny"].ApprovalHandleris a sync or async callable fromApprovalRequesttoApprovalDecision.
These aliases make extension signatures precise. Pass framework names through
adapter= and harness names through agent=.
Query and Bind¶
import kedi
@kedi.query(
model=...,
adapter=...,
agent=...,
system=...,
effort=...,
settings=...,
tools=(),
env=...,
mcp_servers=(),
approval=...,
hooks=...,
skills=...,
artifacts=...,
conversation=...,
cache=False,
)
def function(value: str) -> str: ...
The function docstring starts with kedi and contains a procedure body, not
a full top-level program. The Python stub body is never executed. A normal
function produces a sync wrapper; an async function produces an async wrapper
that offloads blocking adapter work.
import kedi
@kedi.bind(
file="workflow.kedi",
reload=False,
cache=False,
# same backend/profile arguments as query
)
def function(value: str) -> str: ...
bind resolves the path relative to the decorated function's source file,
loads a complete Kedi program, passes call arguments as runtime globals, and
runs top-level main. reload=True reparses when invoked; cache=True enables
the response cache. The Python return annotation informs static typing but the
Kedi return remains the runtime authority.
Configuration¶
configure(...) accepts model, mutually exclusive adapter/agent,
system, effort, settings, tools, env, mcp_servers, approval,
hooks, skills, artifacts, conversation, parallel, max_workers,
loop_iteration_limit, and
adapter-specific keyword arguments.
Each call rebuilds defaults; it does not merge with a previous configure.
context(...) accepts the same values and merges them over current
configuration for sync or async with, restoring the previous ContextVar state
on exit. parallel(max_workers=8) is shorthand for a parallel context.
reset_config() restores library defaults.
Effective environment precedence is configured/local tools, call arguments, automatically registered types, configure environment, then progressively local context/query/bind environment. Name collisions in tool arguments fail rather than silently selecting one source.
Tool and Type Decorators¶
import kedi
@kedi.tool(
name=None,
description=None,
retries=0,
risk="mutating",
)
def tool_name(value: str) -> object: ...
Risk is read_only, mutating, or sensitive. Retries must be nonnegative and
produce retries + 1 total attempts. Sync and async functions are preserved;
only Exception subclasses are retried.
@kedi.type converts an ordinary class to a dataclass or preserves an existing
Pydantic/dataclass surface. inject=True registers it by name for query
annotations in the defining module; inject=False removes that implicit
registration while the class can still be supplied through env.
Adapter Structured Output¶
Structured-output adapters accept ordinary prompt text through template; this
low-level argument does not require Kedi template syntax. Choose one output form:
from typing import Annotated
from pydantic import BaseModel
class Review(BaseModel):
accepted: bool
reason: str
dynamic = await adapter.produce(
template="Evaluate the proposal.",
output_schema={
"accepted": Annotated[bool, "Whether the proposal should proceed"],
"reason": Annotated[str, "Short justification"],
},
)
typed = await adapter.produce(
template="Evaluate the proposal.",
output_type=Review,
)
The first Annotated argument is the field type and the second string is its
model-facing description. output_schema dynamically defines named result
fields; output_type returns the supplied prebuilt type. If both are supplied,
the field schema takes precedence. Pydantic AI, LangChain, DSPy, Claude, Codex,
and WebGPU support both forms. ACP does not currently support structured output
and raises NotImplementedError from produce().
Artifacts and Sessions¶
ArtifactPolicy validates memory/file storage, size threshold, TTL, bounded
preview/read limits, quota, record count, and cleanup interval. artifacts=
accepts a policy, mapping, boolean, or None on configure, context,
query, and bind.
session(state=None) is a synchronous and asynchronous context manager. It
creates or activates a ConversationState so calls can share portable model
history and artifact ownership. Kedi remains stateless by default.
Public artifact models are ArtifactRef, ArtifactChunk,
ArtifactSearchResult, ArtifactReleaseResult, and ArtifactHandle. See
Artifacts and Sessions.
Interactive Execution¶
interactive(...) -> InteractiveSession creates a synchronous, process-local
incremental runtime. InteractiveSession.execute(source, *, source_name=None)
parses and executes one complete fragment exactly once while retaining earlier
values, declarations, imports, conversation state, and artifacts. It returns
the same native result as KediRuntime.run_main(). close() is idempotent;
the session is also a context manager.
dump_session(session, path) atomically writes a strict, pickle-free snapshot
or raises SessionDumpError without changing the destination.
load_session(path, *, session_type=InteractiveSession, adapter=None,
executor=None, engine=None, conversation_state=None) restores source-backed
declarations and saved native state without replaying executable fragments.
session_type is keyword-only and may be an InteractiveSession subclass.
The InteractiveSession.dump() and InteractiveSession.load() methods expose
the same operations. Invalid, modified, or incompatible snapshots raise
SessionLoadError.
See Interactive Execution for supported
configuration, source identity, failure semantics, restrictions, and the
kedi --idle frontend.
Approvals¶
@kedi.approval installs a sync or async handler in current configuration and
returns the same callable. Policies are ApprovalPolicy.allow(),
ApprovalPolicy.deny(), ApprovalPolicy.dynamic(handler), or the strings
"allow"/"deny".
ApprovalRequest fields are tool_name, immutable deep-copied arguments,
risk, adapter_shortname, description, immutable optional metadata,
reason, and tool_reason_enabled. The reason is a model-provided explanation,
not evidence that a call is safe; it is not passed to the underlying tool.
Handlers return:
kedi.ApprovalDecision.allow(reason=None)
kedi.ApprovalDecision.deny(reason=None)
kedi.ApprovalDecision.edit(arguments, reason=None)
Only edit may carry replacement arguments. Edited calls are reclassified and validated before execution.
Hooks and Decision Evidence¶
@kedi.on(event) accepts an event name or a sequence of names. Handlers can
observe events or return the supported decision for that event; consult
Hooks from Python for ordering and registration scope.
capture_decisions() retains decision evidence within a capture context.
decision_info(binding) inspects evidence associated with a binding rather than
re-evaluating it. See Decision Evidence for lookup
arguments, record fields, lifetime, mutation invalidation and cache omissions.
MCP¶
kedi.McpServerSpec(
transport="stdio",
command="server",
args=(),
env=None,
url=None,
headers=None,
).normalized()
Canonical transports are stdio, sse, and http. Stdio requires command;
remote transports require url. Normalization removes fields inapplicable to
the selected transport. MCP lists append across configuration scopes.
Cache and Concurrency¶
cache_info() returns frozen CacheInfo(parse_entries, response_entries).
clear_cache() clears parse/completed-response caches and advances generation
so stale in-flight calls cannot repopulate them.
KediPromise.resolve() returns the concrete value; .map(fn) derives without a
worker slot. force(value) resolves only a Kedi promise. Concrete use of an
unresolved promise raises KediPromiseLeak; repr() is non-forcing.
Low-Level Runtime¶
KediRuntime is the compiled container. Common operations are run_main(),
set_initial_globals(mapping), drain(), procedure/main decorators,
m(expressions), invoke(expressions, capture=...), trace inspection, and
execution-error construction.
i(name), o(name, pytype=None), and c(procedure, *args) construct low-level
input, output, and call expressions for KediRuntime.m().
Executor is the runtime-checkable embedded-Python protocol; DefaultExecutor
uses host eval/exec and is not sandboxed. MarkdownDebugExporter records
code and values but does not redact secrets.
See the Python API guide for complete examples and scope behavior.