Skip to main content

Python SDK client for the Keystone agent evaluation + sandboxed-execution platform

Project description

Keystone SDK for Python

Python client for the Keystone agent evaluation + sandboxed-execution platform. Shares a single source of truth with the TypeScript and Go SDKs — byte-identical cost estimates and prompt rendering across all three.

Install

pip install polarity-keystone

Zero external runtime dependencies — uses only urllib from the standard library.

60-second quick start: Eval()

The shortest path from "I have an agent" to "I have an evaluation":

from polarity_keystone import Eval, Factuality, AnswerRelevancy

result = Eval(
    "summarisation-quality",
    data=[
        {"input": "Long article about whales...", "expected": "Whales are mammals."},
        {"input": "Article about Java GC...",     "expected": "Java GC reclaims memory."},
    ],
    task=lambda input: my_agent(input),                # your agent / prompt
    scores=[
        Factuality(model="paragon-fast"),
        AnswerRelevancy(),
    ],
    max_concurrency=4,
)

print(result.summary)                                   # p50/p95/mean per scorer

If KEYSTONE_API_KEY is set, the run is also recorded to your dashboard; otherwise it stays purely local. Same shape in TypeScript and Go.

Sandbox-as-a-tool ergonomics

create() / get() / list() return a bound SandboxHandle so an agent loop can call the sandbox without threading the ID:

sb = ks.sandboxes.create(spec_id="spec-123")

sb.exec("python script.py")
sb.write("/tmp/input.json", json.dumps(payload))
out = sb.read("/tmp/output.json")
diff = sb.diff()

sb.destroy()

Same pattern on ExperimentHandle and AgentSnapshotHandle:

exp = ks.experiments.create("nightly", spec_id="s")
results = exp.run_and_wait(scores=[Factuality(), ExactMatch(expected_key="expected")])
cmp = exp.compare(other_exp)                            # handle or string ID
m   = exp.metrics()

snap = ks.agents.upload("codex", "./bundle", entrypoint=["python3", "agent.py"])
snap.delete()

The handles delegate field access to the underlying dataclass, so reading sb.id, exp.status, snap.version keeps working unchanged. The old service-level methods (ks.sandboxes.run_command(id, …), ks.experiments.run(id)) stay too — handle methods just call them.

Auto-instrument every LLM client at once

from polarity_keystone import auto_instrument

auto_instrument(sandbox_id=os.environ.get("KEYSTONE_SANDBOX_ID"))
# Patches every installed provider in-place. Subsequent OpenAI/Anthropic/
# Mistral/Google/LiteLLM/Claude Agent SDK/DSPy/LangChain calls auto-trace.

Wraps OpenAI, Anthropic, Mistral, Google GenAI, LiteLLM, Claude Agent SDK, DSPy, LangChain in one call — every prompt, token count, and tool call shows up in your dashboard with no other code changes.

Manual tracing when you want it

from polarity_keystone import traced

# 1. Decorator
@traced
def fetch_user(uid: str) -> dict:
    return db.users.find(uid)

# 2. Named decorator
@traced(name="planning-phase")
def plan(prompt: str) -> str:
    return llm.complete(prompt)

# 3. Context manager
with traced(name="embed-doc"):
    openai.embeddings.create(...)

Spans automatically nest using contextvar-based parent linking — no need to plumb a context object through your code.

What's in the SDK

  • 9 client servicessandboxes, specs, experiments, alerts, agents, datasets, scoring, export, prompts
  • 3 bound handlesSandboxHandle, ExperimentHandle, AgentSnapshotHandle with delegated methods
  • 29 built-in scorers across 5 families:
    • Heuristic (6): ExactMatch, Levenshtein, NumericDiff, JSONDiff, JSONValidity, SemanticListContains
    • LLM-judge (9): Factuality, Battle, ClosedQA, Humor, Moderation, Summarization, SQLJudge, Translation, Security
    • RAG (8): ContextPrecision, ContextRecall, ContextRelevancy, ContextEntityRecall, Faithfulness, AnswerRelevancy, AnswerSimilarity, AnswerCorrectness
    • Embedding (1): EmbeddingSimilarity
    • Sandbox invariants (5): FileExists, FileContains, CommandExits, SQLEquals, LLMJudge
  • @Scorer decorator — wrap any (scenario) -> score function
  • Eval(name, data, task, scores) — Braintrust-style one-call eval primitive
  • @traced decorator + context manager — auto-capture spans with contextvar-based propagation
  • Client wrappingks.wrap(openai_client, sandbox_id=...) adds transparent trace reporting (sync / async / streaming)
  • auto_instrument() — single call patches every installed provider (OpenAI, Anthropic, Mistral, Google GenAI, LiteLLM, Claude Agent SDK, DSPy, LangChain)
  • Prompt managementks.prompts.create(slug, template) / ks.prompts.get(slug) / Prompt.render(**vars) with server-side audit + byte-identical local renderer
  • Bulk exportks.export.traces(...), .spans(...), .scenarios(...), .scores(...) auto-paginate; ks.export.experiment(id) for full JSON or NDJSON dumps
  • OpenTelemetry bridgewrap() emits gen_ai.* metadata; register_otel_flush() piggy-backs on program shutdown

Versioning

Semver. 0.x = alpha/beta while the API shape settles.

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

polarity_keystone-0.2.5.tar.gz (80.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

polarity_keystone-0.2.5-py3-none-any.whl (81.2 kB view details)

Uploaded Python 3

File details

Details for the file polarity_keystone-0.2.5.tar.gz.

File metadata

  • Download URL: polarity_keystone-0.2.5.tar.gz
  • Upload date:
  • Size: 80.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.1

File hashes

Hashes for polarity_keystone-0.2.5.tar.gz
Algorithm Hash digest
SHA256 81f6a8d04d48b3b3046ede337f5eef85d382466b745347b748cdefdebfaff12f
MD5 dcd9c0286f9606acf14789eb82a2d08e
BLAKE2b-256 e5e381f3fe5b07ae60863e5cdfd595a45e430576396a5db00ccc29d329b50803

See more details on using hashes here.

File details

Details for the file polarity_keystone-0.2.5-py3-none-any.whl.

File metadata

File hashes

Hashes for polarity_keystone-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 7b9d279a9695281aca73bdc53674b5b29e1612c831d65357d3b974ad4bd08238
MD5 16f660301cd77f0537982759368516c2
BLAKE2b-256 ddd02be3b950497e19df82956be46fad0628ca3fdd08f0e5ba72fa791ab16550

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page