Compatibility matrix¶
This guide tells you which kneo-client release supports which kneo_serv platform version, what forward and backward compatibility mean in practice, and how to use the drop-to-transport escape hatch when you need access to an endpoint the current kneo-client release doesn't wrap yet.
What "compatibility" means in kneo-client¶
The Kneo Agent Platform's /v1 HTTP API is a stability boundary — a kneo-client release pinned to one kneo_serv minor works against any patch-level kneo_serv release on the same minor line, and against newer minors that don't break /v1.
The pinning is explicit and committed: schemas/openapi.json is a /v1-filtered copy of one specific kneo_serv release's published OpenAPI spec. Bumping the pin is a deliberate PR (via scripts/bump_schemas.py), reviewed in isolation, and never happens automatically. See ADR-004 for the rationale.
Current matrix¶
kneo-client |
Pinned to kneo_serv |
Tested against | Python | Status |
|---|---|---|---|---|
1.1.0 |
v1.2.0 (info.version 1.2.0) |
kneo_serv 1.2.x line (E2E) + 1.0.x/1.1.x per the floors below |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Current |
1.0.0 |
v1.0.0 (info.version 1.0.0) |
kneo_serv 1.0.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Previous |
0.10.0 |
v1.0.0 (info.version 1.0.0) |
kneo_serv 1.0.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Older |
0.9.0 |
v1.0.0 (info.version 1.0.0) |
kneo_serv 1.0.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Older |
0.8.0 |
v0.11.0 (info.version 0.11.0) |
kneo_serv 0.11.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Older |
0.7.0 |
v0.9.0 (info.version 0.9.0) |
kneo_serv 0.9.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Older |
0.6.0 |
v0.7.0 (info.version 0.7.0) |
kneo_serv 0.7.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Older |
0.5.0 |
v0.5.0 (info.version 0.5.0) |
kneo_serv 0.5.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Older |
0.4.0 |
v0.4.0 (info.version 0.4.0) |
kneo_serv 0.4.x line |
>=3.12 (3.12 / 3.13 / 3.14 in CI) |
Older |
kneo_serv declared general availability at v1.0.0 — the /v1 HTTP API and
kneo CLI are stable contracts across the 1.x line. kneo-client is GA at
1.0.0: it pins that v1.0.0 contract and freezes its own public Python API
(the curated __all__) + SemVer across the 1.x line (see
contract_stability.md). The GA surface was
landed across 0.9.0 (the v1.0.0 contract uptake) and 0.10.0 (the
pre-freeze surface corrections); 1.0.0 is the posture declaration over that
corrected, machine-pinned surface.
The pinned kneo_serv version is recorded in schemas/SOURCE.md — that's the source of truth for which platform version generated the committed _generated/ tree.
How pinning works in practice¶
The pin is the input to the generated layer. When you bump it:
scripts/bump_schemas.pyfetches the newopenapi.jsonfrom the targetkneo_servref (or a local checkout).- The spec is filtered to
/v1paths only —kneo_servmounts every route at both/v1/…and/…; we drop the unprefixed mounts. - The filtered spec replaces
schemas/openapi.json,schemas/SOURCE.mdis updated, and_generated/is regenerated. - The hand-rolled adapter layer (
platform/,agent/) may need updates if endpoints were added, renamed, or had their shapes change. The contract testtests/contract/test_path_coverage.pycatches both sides of that drift.
A kneo-client minor release ships exactly one kneo_serv pin. A pin bump lands in a minor; patches never change pins (aligned with contract_stability.md — the earlier "any minor / patch" wording here contradicted it).
Forward compatibility — newer kneo_serv than the pin¶
kneo-client ships an explicit list of every (method, path) it wraps. A newer kneo_serv that adds endpoints will still work for everything kneo-client already wraps — you just won't have wrappers for the new endpoints until the next kneo-client release.
If you need access to a new endpoint before that release, use the public KneoClient.request() escape hatch:
async with KneoClient.from_profile() as client:
# Call an endpoint that doesn't have a wrapper yet:
resp = await client.request("GET", "/v1/some/new/endpoint")
payload = resp.json()
KneoClient.request(method, path, ...) is part of the stable 1.x contract — the supported forward-compatibility path. It runs the full pipeline (auth, retries, idempotency, request-ID injection, and error mapping, just like the wrapped methods) and hands back the raw httpx.Response for you to parse — you just lose the typed response model. Prefer a typed .platform / .agent wrapper whenever one exists. (The older client._transport.request(...) still works but is internal and unsupported; migrate to client.request(...).)
Backward compatibility — older kneo_serv than the pin¶
kneo-client X.Y.Z is not guaranteed against kneo_serv releases older than its pin. Wrappers may rely on response fields that older kneo_serv versions don't emit, and the client's error mapping assumes the current platform error shape. A KeyError on from_dict() is the typical symptom — the wrapper expects a field that wasn't in the older platform's response.
If you have to talk to an older kneo_serv, pin to a matching kneo-client minor:
Need to talk to kneo_serv… |
Use kneo-client |
|---|---|
1.0.x / 1.1.x |
1.1.0 (pinned to v1.2.0) is deliberately older-serv-safe for this uptake: the credential inventory is normalized client-side (status derived from present against pre-1.2.0 servers), and the new surfaces degrade explicitly per the server-version floors below (422 unknown_query_parameters for filter kwargs the server doesn't know, 404 for the graph/preview endpoints, absent usage/trace flags). 1.0.0 (pinned to v1.0.0) also works for everything it wraps. |
0.12.x / 1.0.x |
0.9.0 (pinned to v1.0.0). Takes up the GA contract: async_mode now honored on POST /v1/specs/run (202), the spec_path_confined 422 from default-on spec-path confinement, and consolidated client API-stability docs. A v0.11.0-pinned client (0.8.0) also works against 0.12.x/1.0.x for everything it wraps — specs.run async just surfaces the queued run via the same RunCreateResponse, and an out-of-root spec_path draws the 422 either way. |
0.10.x / 0.11.x |
0.8.0 (pinned to v0.11.0). Absorbs the kneo_serv 0.11.0 /v1 breaks (async run-create 202, unknown-query-param 422 rejection, guardrail-block run terminalization) and adds a versioned User-Agent + Retry-After HTTP-date parsing. v0.10.0 introduced no /v1 change, so a v0.9.0-pinned client (0.7.0) also works against 0.10.x for everything it wraps. |
0.8.x / 0.9.x |
0.7.0 (pinned to v0.9.0). Adds the skill-catalog wrapper (agent.skills.list), the per-request skills overlay on runs.create, Page.window, the typed 400 / 413 / 422 errors, and code-aware 409 classification. A v0.7.0-pinned client (0.6.0) still works against 0.8.x/0.9.x for everything it wraps — it just won't expose those additions. |
0.6.x / 0.7.x |
0.6.0 (pinned to v0.7.0). Adds the audit-events pagination + sorting kwargs (offset / sort_by / sort_order, server-honored since kneo_serv 0.6.0), the standardized error envelope, and the HumanTaskResponse.messages thread projection. A v0.5.0-pinned client (0.5.x) still works against 0.6.x/0.7.x for everything it wraps — it just won't expose those additions. |
0.5.x |
0.5.0 (pinned to v0.5.0). Because the /v1 contract is byte-identical to v0.4.0, a v0.4.0-pinned client (0.1.x–0.4.x) also works against 0.5.x — you just won't surface the typed KneoServiceUnavailableError for the new 503 backpressure path. |
0.4.x |
0.1.x, 0.2.x, 0.3.x, or 0.4.x (all pinned to v0.4.0; pick 0.4.x to drop the long-deprecated audit.list kwargs, 0.3.x for the additive filter kwargs on runs.checkpoints / credentials.list, 0.2.x for the Page + Map return-type ergonomics) |
(More rows added as the project ships.)
Server-version floors and behavior changes¶
Some wrapped surfaces depend on the server actually implementing them — the client sends the request either way, so know your deployment's kneo_serv version:
overlaysare applied only fromkneo_serv0.9.0. Older servers accepted theoverlays(andoverrides/stricton the specs routes) fields but silently ignored them. From 0.9.0 they are actually applied server-side (and replayed on resume). A deployment upgradingkneo_servfrom0.7.xto0.9.xwill see previously-ignored overlay fields in stored request payloads take effect — audit those payloads before upgrading.- Skill catalog requires
kneo_serv >= 0.8.0.client.agent.skills.list()404s against older servers. The per-requestskillsoverlay onruns.createrequires>= 0.9.0. - Human-task
statusfilter requireskneo_serv >= 0.8.0.human_tasks.list(status=...)is silently ignored by older servers (honored from 0.8.0, contractual in the 0.9.0 spec). - Spec-explain envelope requires
kneo_serv >= 0.9.0. Theenvironment/overlays/overridesfields onspecs.explain(including the explain leg ofdry_run) draw a 422 from older servers. - Run-list filters,
session_id, and the graph endpoints requirekneo_serv >= 1.1.0;q,usage, policy preview, the typed credential-inventory fields, and the tracecomplete/droppedflags require>= 1.2.0. Older servers hard-reject unknown query params with422 unknown_query_parameters(they never silently ignore them), 404 the graph/preview endpoints, and simply don't emit the new response fields. A bodysession_idonruns.create/specs.rundraws a body-validation422fromkneo_serv 1.0.x(extra='forbid'), andPOST /v1/specs/runsilently dropped it until the1.2.0parity fix. - Timestamp filters compare lexically on
kneo_serv 1.1.x.created_after/created_beforeare validated + UTC-normalized (malformed values →422 invalid_timestamp) only from1.2.0; on1.1.xa malformed or non-+00:00-form value silently misfilters. Passdatetime.isoformat()of a tz-aware UTC datetime. - Resuming an expired human task raises
KneoHumanTaskExpiredErrorfromkneo_serv >= 1.1.0(409human_task_expired; tasks withon_timeout: escalatestay resumable late). Older servers could let a late resume race the expiry sweep and succeed. kneo_servbehavior changes worth auditing before a server upgrade to1.1.x/1.2.x(no client code change; listed here because runs that used to pass may fail): spec content now rejects unknown keys (extra='forbid'→E_SCHEMAdiagnostics; provider-specific params belong undermodel.extra); toolallowed_domains/denied_domainsare enforced at call time (422 guardrail_violationsync /failedasync); a run's spec + skills are frozen at create (edit-then-resume no longer applies the edit, from1.1.0); the per-run policy-report scope changedspecs:read→runs:read;GET /v1/skillspathvalues are now root-relative.- Spec-path confinement is default-on from
kneo_serv >= 1.0.0. A caller-suppliedspec_path,overlaysentry, orskills[].sourcethat resolves outside the server's allow-listed root (KNEO_SERV_SPEC_ROOT, defaulting to the server's working directory) — including absolute,..-traversal,~, or symlink-escape paths — is rejected422 spec_path_confined(surfaced asKneoValidationErrorwith.code == "spec_path_confined"). Through0.12.xthis was opt-in (out-of-root paths only logged a deprecation warning); at1.0.0the warn-and-allow path is removed. The client sends these fields unchanged either way — keep your specs under an allow-listed root, or have the operator setKNEO_SERV_SPEC_ROOT. See error handling.
Breaking changes¶
A breaking change in either direction triggers a major bump:
kneo-clientmajor — the public Python API (kneo_client.*namespace) changes incompatibly. Very rare.kneo_servmajor — i.e., introduction of/v2.kneo-clientmay need a major bump if/v1is sunset; otherwise it ships a new minor that supports both.
Within a major, deprecated surfaces keep aliases for at least one minor. See the API stability contract for the full SemVer + deprecation policy.
Verifying compatibility yourself¶
The simplest smoke is the bundled examples. They ship in the repository (not in the wheel), so run them from a checkout:
# Install a specific kneo-client version
python -m pip install "kneo-client==X.Y.Z"
# Grab the MATCHING examples — check out the same release tag, or the
# examples may use surface the installed wheel doesn't have
git clone --branch vX.Y.Z https://github.com/kneo-agent/kneo-client.git && cd kneo-client
# Point it at your kneo_serv instance
export KNEO_URL=https://your-kneo-serv.example.com
export KNEO_API_KEY=...
# Run the smoke (touches health, runs, audit, agent specs, and human tasks)
python examples/01_basic_run.py YOUR_SPEC_ID
The seven examples/ scripts collectively touch the platform health, runs, audit, agent spec, and human-task surfaces — enough to catch obvious incompatibilities in seconds.
For deeper validation, the integration test suite is env-gated; set KNEO_TEST_URL and KNEO_TEST_API_KEY and run python -m pytest tests/integration -v.
What the pin does not guarantee¶
The pin guarantees the wire format and the path set of /v1. It does not guarantee:
- Provider availability — whether your
kneo_servdeployment has GPT-4 configured, an MCP server reachable, a specific runtime registered. The pin says nothing about deployment state. - Spec compatibility — a spec that works on one
kneo_servmay fail on another if the spec relies on a specific provider, tool, or platform version. Validate specs against the target environment withclient.agent.specs.validate(...). - Policy outcomes —
policies.environment_*queries return whatever policy is configured on the target deployment.
These are platform-deployment concerns, not client-library concerns. The client gives you a clean wire to the platform; what the platform allows is a separate dimension.