Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

ctxmesh — Python SDK

Typed clients for agents running on ctxmesh, the Kubernetes-native control plane for AI agents.

Your agent runs in a pod beside the platform's sidecars. This SDK is the typed way to reach them — conversation memory, tools and MCP servers, knowledge bases, model calls, and feedback — plus OpenTelemetry step tracing that produces the same trace tree a framework agent gets.

Your code never holds credentials. Endpoints and identity arrive in the environment the platform injects, so there is no API key to manage and no base URL to configure.

pip install ctxmesh

The SDK is optional by design: every capability here is also a plain HTTP endpoint the platform serves, so an agent in any language can call the contract directly.

  • Distribution name: ctxmesh · import name: ctxmesh
  • Python: 3.9+ · runtime deps: the plane clients are pure stdlib; the model + step-tracing helpers add a minimal OTLP/gRPC exporter + OpenInference semantic-convention constants, pinned to the exact versions images/base-python already bundles (opentelemetry 1.27.0, openinference-semantic-conventions 0.1.30) — so import ctxmesh adds zero net footprint to the base image.

Surface

from ctxmesh import agent

client = agent.from_env()          # in-pod: reads the launcher-injected env

# memory (:2998)
client.memory.get()                       # full context (list)
client.memory.put([{"role": "user", "content": "hi"}])
client.memory.append({"role": "assistant", "content": "hey"})
client.memory.search("hi")
# bind a conversationId for the turn (the agent reads it from the request):
turn = client.with_conversation("conv-42")
turn.memory.get()

# tools / discovery (:2999)
client.tools.list()                       # live manifest as Tool objects
client.tools.call("word-count", text="a b c")   # MCP tools/call

# feedback (:2995)
client.feedback.score("trace-abc", "thumbs-up", 1, comment="great")

# model gateway ($MODEL_GATEWAY_URL) — emits an OpenInference LLM span
resp = client.model.chat("gpt-4o-mini", [{"role": "user", "content": "q"}])
resp.text        # the completion; resp.usage → token counts; resp.raw → full body

agent.from_env() fails fast (NotInPodError) when no launcher env is present — it never silently no-ops. For tests / offline use, build a PlaneConfig explicitly (PlaneConfig.for_test(...)) and call agent.from_config(config) against an in-process fake, so tests need no cluster.

Step-tracing helpers (custom loops)

A framework agent (LangChain/OpenAI/Anthropic) gets its step → tool → model trace tree SDK-free via base-image OpenInference auto-instrumentation. A custom, no-framework loop has no inferable step boundaries, so it emits the tree explicitly with client.trace.* — producing an OpenInference tree structurally identical to a framework one (same CHAIN/TOOL/LLM span kinds + attribute keys), exported over the same OTLP/gRPC path to the collector (:4317) → Langfuse.

# Bind the inbound /invoke request so the WHOLE tree roots under the launcher's
# `agent.invoke` span (the launcher injected a W3C `traceparent`). Without this
# bind the SDK spans would start a detached trace.
with client.trace.request_context(request.headers):
    with client.trace.step("plan") as step:            # CHAIN span
        step.set_input(user_prompt)
        plan = client.model.chat(model, messages)       # nested LLM span (auto)
        with client.trace.tool("web_search", args) as t:  # TOOL span (child of step)
            t.set_output(client.tools.call("web_search", **args))
        step.set_output(plan.text)

client.trace.loop(name, headers=request.headers) is a convenience that binds the request context and opens the AGENT loop-root span in one with.

Rooting under agent.invoke is the invariant — the SDK extracts the W3C traceparent the launcher proxy injects on every /invoke and makes the step spans children of the launcher's agent.invoke root (same trace id, correct parent span id), not a detached trace.

Offline / telemetry resilience: when OTEL_EXPORTER_OTLP_ENDPOINT is unset (offline/tests) the trace client runs in no-op export mode — spans are still created (so nesting/propagation still works and can be asserted) but exported nowhere. Export/setup failures degrade to no-op and never crash the loop (a telemetry blip is not an error); this is deliberately distinct from the plane clients, which surface endpoint errors (a rejected memory write is a real error).

Serving an agent (ctxmesh.serve)

You don't hand-roll the HTTP server, the /invoke body/​envelope, the /healthz//readyz probes, the $AGENT_PORT the launcher proxies to, the traceparent capture, or the SSE token stream — ctxmesh.serve encodes the whole runtime contract, and it binds request_scope for you (so a custom loop keeps the invoking user's run capability instead of silently downgrading to org/public creds):

import ctxmesh

def handle(req: ctxmesh.InvokeRequest) -> str:
    # req.client is scoped to the caller (capability + granted approvals bound) and
    # conversation-aware (req.conversation_id); req.headers roots the trace.
    with req.client.trace.loop("my-agent", headers=req.headers):
        answer = req.client.model.chat(
            "gpt-4o-mini", [{"role": "user", "content": req.input}]
        )
    return answer.text          # or return a ctxmesh.ManagedResult for steps/tools/approval

ctxmesh.serve(handle)           # blocks; serves /invoke + health on $AGENT_PORT
  • Streaming is transparent: call req.emit_token(delta) as your loop produces content — it emits an SSE token frame when the caller sent Accept: text/event-stream, and is a no-op otherwise (same handler, both modes).
  • The stock managed agent is just ctxmesh.serve() with no handler — it runs the config-driven tool-calling loop (run_managed_loop) with ManagedConfig.from_env(). That is exactly the managed-agent image's entrypoint.
  • serve(handler, *, client=…, agent_name=…, port=…) overrides the env defaults (agent.from_env() / $AGENT_NAME / $AGENT_PORT) — handy for local runs and tests.

examples/sdk-custom-agent shows the same loop with the HTTP handler written out by hand — the "under the hood" reference for what serve collapses into one call.

Documentation

Apache-2.0. Contributor and toolchain notes live in the repository.

Metadata

Release files for ctxmesh 0.1.0b6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ctxmesh 0.1.0b6
File Size Uploaded
ctxmesh-0.1.0b6.tar.gz 176.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ctxmesh 0.1.0b6
File Interpreter ABI Platform
ctxmesh-0.1.0b6-py3-none-any.whl Python 3 none any Details

Total release size: 297.4 kB

Release files / ctxmesh-0.1.0b6.tar.gz

Download URL ctxmesh-0.1.0b6.tar.gz
Size 176.6 kB
Tags Source
SHA-256 checksum
How to use checksums
bce1c28c2afdb7775e46e874693c36f4bed69596a22c43811484e66ab242a034
BLAKE2b-256 checksum
How to use checksums
662d07c511e363b4b9070e174a19e5e7ed3218615197e3e268c084b78d7e407a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release files / ctxmesh-0.1.0b6-py3-none-any.whl

Download URL ctxmesh-0.1.0b6-py3-none-any.whl
Size 120.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
11f6a37793546aed4fb86ded174a786934fb071ff6de8cded58c2973c829820e
BLAKE2b-256 checksum
How to use checksums
41a0f962588d93cd958f707648dc723455082a0e0824f07276011b3e35f878d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page