Quickstart¶
This guide walks you from a fresh shell to your first authenticated call against a running Kneo Agent Platform instance, then to creating a run and inspecting its trace.
What "quickstart" means in kneo-client¶
kneo-client is a typed Python SDK and adapter toolkit for the Kneo Agent Platform's /v1 HTTP API. Two products use it as their shared client layer — Kneo Agent Dashboard for operations and Kneo Agent Studio for development — but you can use it directly from any Python 3.12+ codebase that needs to talk to a platform instance.
A working setup needs three things:
- The
kneo-clientpackage installed. - A profile — a
(url, api_key, auth_scheme, timeout)tuple resolved from a TOML config file, environment variables, or explicit kwargs. See Profiles and auth for the full resolution model. - A reachable platform instance.
The rest of this page assumes you have all three.
Install¶
Requires Python ≥ 3.12. The runtime closure is small: httpx, pydantic, anyio, platformdirs, attrs. No CLI is installed — kneo-client is a library, not a service.
Verify the install:
Configure a profile¶
The client reads connection details in this order (later sources override earlier):
- A TOML config file at
~/.config/kneo/client.toml(XDG-style location viaplatformdirs). - Environment variables:
KNEO_PROFILE,KNEO_URL,KNEO_API_KEY,KNEO_AUTH_SCHEME,KNEO_TIMEOUT. - Explicit keyword arguments to
KneoClient.from_profile()(or the underlyingload_profile()).
The minimum-friction setup is env vars — useful for one-off scripts and CI:
For named multi-profile setups (e.g. default for prod, staging for non-prod), use the TOML file:
# ~/.config/kneo/client.toml
[default]
url = "https://kneo.example.com"
api_key = "prod-key"
auth_scheme = "bearer"
timeout = 30.0
[staging]
url = "https://staging-kneo.example.com"
api_key = "staging-key"
Switch profiles by name (KneoClient.from_profile("staging")) or by env (KNEO_PROFILE=staging).
See Profiles and auth for the full resolution semantics, both auth schemes, and the multi-profile workflow.
Ping the platform¶
The smallest possible script — verifies that auth flows correctly and the platform is reachable:
import asyncio
from kneo_client import KneoClient
async def main():
async with KneoClient.from_profile() as client:
ready = await client.platform.health.readyz()
print(f"platform ready: ok={ready.ok} version={ready.service!r}")
asyncio.run(main())
What this exercises:
- Profile resolution (TOML / env / kwargs).
- API-key injection on the outgoing request (
Authorization: Bearer …orX-Kneo-Api-Key: …depending on scheme). - The transport's retry loop (will retry on transient network failures).
- Error mapping (a missing key surfaces as
KneoAuthError, an unreachable URL asKneoNetworkError).
If you get a KneoAuthError, your API key isn't reaching the platform — re-check the profile resolution chain. If you get a KneoNetworkError, the URL is unreachable. See Error handling for the full hierarchy.
Create your first run¶
A run is the unit of work the platform executes — it instantiates a spec (an agent definition) and tracks its lifecycle through queued → running → terminal {completed, failed, cancelled}. To create one:
async with KneoClient.from_profile() as client:
created = await client.platform.runs.create({"spec_id": "your-spec-id"})
print(f"run_id={created.run_id} status={created.status}")
terminal = await client.platform.runs.wait_for_completion(
created.run_id, poll_interval=2.0, timeout=600
)
print(f"final status: {terminal.status}")
trace = await client.platform.runs.trace(created.run_id, limit=20)
for event in trace.events:
print(event)
The interesting parts:
runs.create(...)auto-injects anIdempotency-Keyheader (UUID4). Re-running the same payload with the same key is safe — the platform replays the original response. See Idempotency and retries.runs.wait_for_completion(...)pollsruns.get(run_id)until the run reaches a terminal status. Default terminal set is{"completed", "failed", "cancelled"}; passterminal_statuses={"paused_human_review", …}to treat additional states as terminal.runs.trace(...)returns events the platform recorded during the run (tool calls, model calls, middleware decisions, policy checks, etc.).
This is the operational core of the platform adapter. Every other endpoint follows the same shape: client.platform.<resource>.<method>(...) returning a typed model.
Sync facade¶
If your caller can't run an event loop (a script, a notebook, a sync framework), wrap the transport with SyncTransport:
from kneo_client.core.profiles import load_profile
from kneo_client.core.transport import SyncTransport
with SyncTransport(load_profile()) as transport:
response = transport.request("GET", "/v1/healthz")
print(response.json())
Under the hood SyncTransport runs Transport inside an anyio.from_thread.start_blocking_portal() — same retry / idempotency / error flows, called synchronously. The async surface is the recommended path; the sync facade is for ergonomics.
SyncTransport does not mount .platform / .agent adapters — those are async-only. Sync consumers wanting wrapped endpoints either glue async-to-sync at the call site or drop to transport.request(method, path, ...) directly.
Where to go next¶
By topic:
- Profiles and auth — multi-profile workflows, the two header schemes the platform supports, environment-variable precedence.
- Idempotency and retries — when keys are auto-injected, how 409 mismatches surface, customizing the retry policy.
- Pagination — walking large result sets across list endpoints.
- Error handling — the full exception hierarchy and what to catch.
- Compatibility matrix — which
kneo-clientreleases support whichkneo_servversions.
For the comprehensive API reference (every class, method, exception), see the API Reference HTML or the PDF version.
For runnable end-to-end scripts: examples/.