Official Python SDK for Ysaere — traceable swarm intelligence with provenance on every claim.
Project description
ysaere
Official Python SDK for Ysaere — multi-agent research swarms that return a report and the evidence chain behind it.
Every completed run carries a Trust Receipt: a hash chain over each agent's
inputs and outputs, signed with both Ed25519 and ML-DSA-65 (FIPS 204,
post-quantum) and checkable by anyone against the public keys at
https://api.ysaere.com/.well-known/trust-keys — without trusting our answer.
pip install ysaere
Six lines
from ysaere import Ysaere
y = Ysaere() # reads YSAERE_API_KEY
report = y.run_and_wait("dd-report", "Acme Corp") # submit, then poll
print(report.text) # markdown
print(report.sources) # what it actually read
print(report.content_hashes) # section -> v2:sha512:...
Get a key at https://app.ysaere.com/developer/keys. New accounts start with 150 free credits — enough to run Angel Intelligence (50) and Angel Deep (90) before spending anything.
Two shapes of call
Swarm runs take minutes and return a run_id you poll:
run = y.company_intelligence("Acme Corp") # 202, queued
print(run.credits_consumed, run.balance_remaining)
report = y.wait(run) # blocks until terminal
Sync micro-SKUs answer in one response and return a plain dict — there is no
run_id and nothing to poll:
y.classify("Acme Corp") # 10 credits
y.quick_brief("Acme Corp", focus="key risks") # 20
y.sourced_brief("Acme Corp", sources=["web", "vault"]) # 40, with citations
y.vault_search("cap table") # 5, your own files
run() refuses a sync endpoint outright rather than handing back an empty Run.
Catalog
| Method | Endpoint | Credits |
|---|---|---|
vault_search |
vault-search |
5 |
classify |
classify |
10 |
quick_brief |
quick-brief |
20 |
retail_insights |
retail-insights |
25 |
sourced_brief |
sourced-brief |
40 |
angel_intelligence |
angel-report |
50 |
security_assessment |
security-scan |
75 |
retail_insights_deep |
retail-insights-deep |
75 |
angel_deep |
angel-deep-report |
90 |
company_intelligence |
ci-report |
100 |
market_intelligence |
market-report |
150 |
due_diligence |
dd-report |
200 |
This is the same surface @ysaere/sdk and @ysaere/cli expose — one product
definition across all three clients. The REST API serves more than this; reach
anything else through y.request(...).
Pricing is answerable offline — the catalog ships with the package:
from ysaere import credits_for
credits_for("dd-report") # 200
credits_for("dd") # 200 — short alias
credits_for("due_diligence") # 200 — MCP tool name
y.estimate("dd-report") asks the server instead. Neither debits anything.
Errors you can act on
from ysaere import InsufficientCreditsError, X402PaymentRequiredError
try:
report = y.run_and_wait("dd-report", "Acme Corp")
except InsufficientCreditsError as e:
print(e.required, e.balance, e.topup_url) # enough to recover automatically
except X402PaymentRequiredError as e:
print(e.pay_to, e.max_amount_required) # pay on-rail with your own signer
The SDK never signs an x402 challenge for you. Ysaere does not custody keys and
neither does this client: you get the challenge, you decide, you retry with your
own X-PAYMENT header via y.request(..., extra_headers={...}).
Also raised: AuthenticationError (401), PermissionError_ (403),
NotFoundError (404), RateLimitError (429), NotImplementedYetError (501 —
published but not yet wired, never retried), ServerError (5xx),
ValidationError (400), TimeoutError_, and UsageError for a call that was
wrong before it left the process. PaymentRequiredError is the base of both
402 shapes, if you want to catch them together.
Waiting
wait() defaults to a 1,800-second budget. That number is measured, not
advertised: Company Intelligence runs about 1,185 seconds and Market
Intelligence about 2,119. If the budget expires you get TimeoutError_ carrying
the run_id — the run keeps going and nothing is lost:
try:
report = y.wait(run, timeout=300)
except TimeoutError_ as e:
report = y.get_report(e.run_id) # later, from anywhere
Or skip polling entirely:
y.create_webhook("https://you.example/hook", events=["report.completed"])
Deliveries are HMAC-signed in X-Ysaere-Signature, with X-Ysaere-Event and
X-Ysaere-Delivery alongside for idempotent handling.
Retries, and where they stop
Replayable requests retry 429/500/502/503/504 with exponential backoff,
honouring Retry-After. Swarm submits carry an auto-generated Idempotency-Key,
so a retried submit replays the original acceptance instead of debiting twice.
Pass your own with idempotency_key=.
Sync micro-SKUs are deliberately not retried on 5xx or on a network timeout. They debit on success and the server does not dedupe them, so a replay could charge twice for work that already happened. A 429 — a rejection before any work — still retries.
501 is never retried. A published-but-unwired endpoint answers the same way
forever.
Async
import asyncio
from ysaere import AsyncYsaere
async def main():
async with AsyncYsaere() as y:
run = await y.due_diligence("Acme Corp")
report = await y.wait(run)
print(report.text)
asyncio.run(main())
Identical surface, every method awaitable.
Traceability
report.provenance["verified"] # chain resolved
report.provenance["agents"] # which agents contributed
report.content_hashes # section_key -> v2:sha512:...
report.sources # every source reference
y.provenance(run.id) # the full chain
y.trust_receipt(run.id) # the signed receipt
y.verify(signature) # public — resolves with no key at all
Citations to your uploaded documents carry a chunk index and a content hash of the exact excerpt the model read, not a page number. A page number says roughly where to look; a content hash proves exactly what was read, and cannot be invented.
Signing proves integrity, not correctness — that an output came from the stated process over the stated sources and has not been altered since.
Nothing is unreachable
Any /v1 path is one call away, with the same auth, retry and error mapping:
y.request("GET", "/marketplace/agents")
y.request("POST", "/intel/ci-report", json={"target": "Acme"},
idempotency_key="my-own-key")
Configuration
YSAERE_API_KEY |
API key. Or pass api_key=. |
YSAERE_BASE_URL |
Defaults to https://api.ysaere.com/v1. |
Ysaere(api_key=..., base_url=..., timeout=60.0, max_retries=3)
Keys come in two kinds. A test key (ysa_test_*) runs in sandbox and debits
nothing; a production key (ysa_prod_*) does the real work. A key is optional at
construction — verify() and pricing() are public — and an authenticated call
without one raises UsageError immediately rather than spending a round-trip to
earn a 401.
Requires Python 3.9+. The only dependency is httpx.
Also available
TypeScript SDK @ysaere/sdk · CLI @ysaere/cli · MCP server at
https://mcp.ysaere.com/mcp · OpenAPI at
https://api.ysaere.com/v1/openapi.json
MIT © Ysaere, Inc.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ysaere-0.1.0.tar.gz.
File metadata
- Download URL: ysaere-0.1.0.tar.gz
- Upload date:
- Size: 22.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72fa56633015d7641a9dbb06259b530573be96a4740014cb0633bd2473f509ef
|
|
| MD5 |
011a55da3bdfb9fc0ab3ea6bf6fe9ea3
|
|
| BLAKE2b-256 |
89ff139eb87ab357bb389fd85163d8f9ce54f0daaff3c3a040854efc48a0e08b
|
File details
Details for the file ysaere-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ysaere-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a4aa28274a3b95a052b629ac2c9bd53d024ca5c023dc867c917c085684f308d
|
|
| MD5 |
0ad0ddf3356b306071f77c0253952d95
|
|
| BLAKE2b-256 |
9e66ce4b2e0eed1c0bfe2a6ef848cfb76eb6bc25c4679a18b7cd715ef18055ce
|