daimon-sdk
Typed async Python SDK for processd-mcp and processd-sandbox-manager.
daimon-sdk wraps the raw MCP tool surface exposed by processd-mcp and presents it as grouped Python APIs such as client.files.read() and client.exec.start_session(). The SDK keeps the monorepo's core project as the contract source of truth and focuses on:
- connection and token wiring
- manager sandbox lifecycle helpers
- typed request/response handling
- structured tool error mapping
- interactive session helpers
- compatibility tests against a real
processd-mcpbinary
Install
pip install daimon-sdk
For local development:
pip install -e ".[dev]"
Quickstart
With a sandbox manager:
import asyncio
from daimon_sdk import DaimonManagerClient
async def main() -> None:
async with DaimonManagerClient("http://127.0.0.1:18080") as manager:
async with manager.sandbox() as sandbox:
runtime = await sandbox.runtime.get_context()
print(runtime.base_workdir)
result = await sandbox.exec.bash("python3 --version")
print(result.stdout or result.stderr)
asyncio.run(main())
Using a processd scheduler
processd-scheduler is wire-compatible with the manager API, so use the same
DaimonManagerClient and point base_url at any scheduler replica. No
separate scheduler client is required:
async with DaimonManagerClient(
"https://processd.example.com",
access_token="cluster-control-token",
) as manager:
sandbox = await manager.create_sandbox()
print(sandbox.id)
Scheduler sandbox IDs are signed, opaque routing tokens. Store and pass them
back unchanged; do not parse them or substitute a manager-local ID. Returned
MCP and service-port URLs already use the scheduler's configured
public_base_url, and sandbox proxy requests continue to use the sandbox's
own token exposed by SandboxInfo/ServicePortInfo.
If you already have a sandbox MCP URL and token, connect directly to MCP:
import asyncio
from daimon_sdk import DaimonClient
async def main() -> None:
async with DaimonClient("http://127.0.0.1:8080/mcp") as client:
runtime = await client.runtime.get_context()
print(runtime.base_workdir)
result = await client.files.glob("**/*.rs", path=runtime.base_workdir)
print(result.filenames[:5])
bash = await client.exec.bash("printf 'hello from processd\\n'")
print(bash.stdout)
asyncio.run(main())
Raw MCP vs SDK
Raw MCP:
payload = await mcp_client.call_tool("Read", {"file_path": "/tmp/demo.txt"})
SDK:
read = await client.files.read("/tmp/demo.txt")
print(read.file.content)
API Overview
DaimonClient(base_url, access_token=None, timeout_s=30.0)await client.connect()/await client.close()async with DaimonClient(...) as clientclient.runtime.get_context()client.files.read() / write() / edit() / glob() / grep()client.exec.bash() / start_session()SessionHandle.write() / poll() / wait_for_exit() / close()client.web.fetch()client.raw.call_tool()DaimonManagerClient(base_url, access_token=None, timeout_s=30.0)await manager.health()await manager.capacity()await manager.create_sandbox()await manager.list_sandboxes(labels=..., states=...)await manager.find_sandbox(labels={"thread_id": thread_id})await manager.find_or_create_sandbox(labels={"thread_id": thread_id})await manager.get_sandbox(id)await manager.start_sandbox(id) / stop_sandbox(id) / delete_sandbox(id)await manager.update_sandbox(id, ttl_seconds=...)async with manager.sandbox() as sandboxawait sandbox.set_ttl(ttl_seconds)sandbox.service_portssandbox.get_service_port(port)sandbox.runtime/files/exec/web/raw
manager.sandbox() creates a sandbox, connects to its MCP endpoint, and deletes
it on context exit by default. Use delete_on_exit=False or
create_sandbox() when the workspace should survive beyond the context.
find_sandbox(labels=...) is a read-only lookup by default and does not extend
the sandbox TTL. Pass ttl_seconds=... only when you intentionally want the
manager's compatibility renew behavior, or use find_or_create_sandbox(...)
for normal acquire/renew flows.
ttl_seconds=0 marks a sandbox as immediately expired so the next manager
reaper loop deletes it.
Sandbox Service Ports
When a sandbox runs a service on a manager-configured port, the SDK exposes the connection information and leaves the request itself to your HTTP or WebSocket client:
import httpx
async with manager.sandbox() as sandbox:
web = sandbox.get_service_port(3000)
response = httpx.get(web.url + "hello.txt", headers=web.headers)
print(response.text)
ServicePortInfo contains only port, url, token, and headers.
Local Testing
The SDK compatibility tests use the sibling core project in this monorepo:
processd/
core/
sdk/
Run tests with an environment that already has the dev dependencies installed:
PYTHONPATH=src python -m pytest -q
The E2E suite builds and launches ../core/target/debug/processd-mcp.
Manager E2E uses the sibling core Docker manager compose path:
PROCESSD_SDK_MANAGER_E2E=1 PYTHONPATH=src python -m pytest -q -m manager_e2e
Multi-replica scheduler E2E uses the sibling scheduler compose file. It starts
two managers and two scheduler replicas, exercises the SDK across both
schedulers, and verifies the 503 unavailable and 410 lost-node states:
PROCESSD_SDK_SCHEDULER_E2E=1 PYTHONPATH=src \
python -m pytest -q -m scheduler_e2e
Release
Releases are published from GitHub Actions when a tag matching v* is pushed.
git tag v0.4.0
git push origin v0.4.0
The tag version must match pyproject.toml's project version.
Metadata
Release files for daimon-sdk 0.6.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| daimon_sdk-0.6.1.tar.gz | 96.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| daimon_sdk-0.6.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 121.8 kB
Release files / daimon_sdk-0.6.1.tar.gz
| Download URL | daimon_sdk-0.6.1.tar.gz |
|---|---|
| Size | 96.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
918f0b91480650c59448504e4e5bc153aa01fe5e8567a33146af8db47a3709b0
|
|
BLAKE2b-256 checksum How to use checksums |
842ba2f0f302e762d33a6c018798362e62788ecc26125f405473e9f536a86956
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 8, 2026.
Transparency logRelease files / daimon_sdk-0.6.1-py3-none-any.whl
| Download URL | daimon_sdk-0.6.1-py3-none-any.whl |
|---|---|
| Size | 25.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
226419b9135eaed10bfb8c7387408ac9a0435794512efc701dee6293c9a39077
|
|
BLAKE2b-256 checksum How to use checksums |
567de44f63745ef87d0e524c288e0796002758afecc417bc07751be867ce38fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 8, 2026.
Transparency logSecurity for daimon-sdk 0.6.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for daimon_sdk-0.6.1.tar.gz
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 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.