Explicit args bypass the config file entirely. Use in tests, notebooks where you want zero environmental dependency, or when the credential lives in a secrets manager.
# Register a Snowflake data platform (BYO).# Skip this entirely for tenants on managed-postgres — Ntropii provisions# the database itself and no integration is needed.integration = client.integrations.create_data_platform_sync( name="Acme Snowflake UK", provider="SNOWFLAKE", region="UK-South", config={ "account": "acme-fund.eu-west-2", "warehouse": "fund_ops", "user": "ntropii", "password": "...", },)# Test the connectionresult = client.integrations.test_connection_sync(integration.id)print(result.success, result.latencyMs)# List + discoverplatforms = client.integrations.list_data_platforms_sync()schemas = client.integrations.discover_schemas_sync(integration.id)
A runbook is the deterministic Python templates that drive a workflow. Runbooks live in runbook-templates/runbooks/<slug>/ and get deployed to the worker. The SDK surfaces them for browsing, fetching the LLM-facing skill definition, and pushing bundles.
# List runbooks currently available on the workerrunbooks = client.runbooks.list_sync()# Fetch one with its full templates manifestdetail = client.runbooks.get_sync("nav-monthly")# Pull the templates payload (workflow.py, activities.py, models.py, skill.md)templates = client.runbooks.templates_sync("nav-monthly")# Submit user feedback against a runbook (optionally tied to a task)client.runbooks.feedback_sync("nav-monthly", "Period close took longer than expected", task_id="...")# Deploy a runbook bundle to the worker (less common — usually via the CLI)result = client.runbooks.deploy_sync( "nav-monthly", version="0.1.0", artifact_url="...", # signed storage URL for the bundle archive)
A workflow binds a runbook to an entity, optionally on a schedule. Per N-80, workflows are anchored to a runbookSlug (the deployed code identifier on the worker); a workflow with a friendly name like "Acme NAV monthly" dispatches to the registered nav-monthly worker code.
# Bind a runbook to an entityworkflow = client.workflows.create_sync( runbookSlug="nav-monthly", entityId="acme-commercial-spv1", name="Acme NAV monthly — SPV 1", schedule="0 8 5 * *", timezone="Europe/London",)# Inspectworkflows = client.workflows.list_sync()detail = client.workflows.get_sync(workflow.id)
Most of the time, you won’t call these directly. The CLI’s
ntro workflow create --path ./runbooks/X/ --tenant T --entity E --schedule … wraps runbook deploy + workflow binding in a single
command. Use the resource accessors here when scripting or building
your own flow.
External agents are references to Managed Agents on host platforms (Anthropic, GitHub/Microsoft, …) that runbook steps can invoke via ntro.workflow.agents.invoke. The SDK surfaces registration and lifecycle.
# Register a reference to an Anthropic-hosted Managed Agent.# `external_ref` encodes both the kind and the host-platform id.agent = client.agents.create_sync( tenantId="byng", kind="claude_managed", external_ref="anthropic://agents/agent_01SxpziMunFrUbnAYkGB5Hu3", name="audit-handover",)print(agent.id, agent.api_key) # api_key is plaintext — shown ONCE# List + getagents = client.agents.list_sync(tenant_id="byng")detail = client.agents.get_sync(agent.id)# Versioning (optional — supports rolling out new agent prompts)version = client.agents.create_version_sync(agent.id, changelog="prompt v2")# Deleteclient.agents.delete_sync(agent.id)
Agents are tenant-scoped. The same Anthropic agent id can be registered under multiple tenants — each registration becomes a separate Ntropii agent row with its own API key.
# Triggertask = client.tasks.create_sync( tenantId="acme-fund", entityId="acme-commercial-spv1", workflowId="nav-monthly", context={"period": "2026-03", "priority": "HIGH"},)# Pollimport timewhile True: task = client.tasks.get_sync(task.id) print(task.status, [s.name for s in task.steps if s.status == "IN_PROGRESS"]) if task.status in ("COMPLETED", "FAILED", "CANCELLED"): break time.sleep(5)# History for an entityhistory = client.tasks.history_sync("acme-fund", "acme-commercial-spv1")