Secure Agent SDK v1.1
Runtime controls and evidence tooling for enterprise AI agents.
Deny-by-default permissions, TEE-isolated execution, immutable audit records, content safety filters, and one-call control mapping for governed deployments.
Installation
Install via npm. Zero runtime dependencies.
# npm npm install @thetazero/agent-sdk # yarn yarn add @thetazero/agent-sdk # pnpm pnpm add @thetazero/agent-sdk
Get your API key from the dashboard under Settings → API Keys. All keys currently have full access — fine-grained scopes are coming Q2 2026.
Quick Start
Three lines to run a sandboxed, governed agent.
const { SecureAgent } = require('@thetazero/agent-sdk'); const agent = new SecureAgent({ apiKey: 'tzk_your_api_key', permissions: SecureAgent.permissions.CODER, limits: { maxMemoryMb: 512, maxExecutionTimeSec: 300 }, sandbox: 'STANDARD', }); await agent.configure(); const result = await agent.run({ task: 'Analyze the user churn data and identify top 3 risk factors', data: { users: churnDataset }, }); console.log(result.output); // ↳ executionId, status, output, durationMs, auditTrailUrl
WASM Sandbox Runtime Phase 1.1
The Phase 1.1 sandbox runtime executes your agent code inside an isolated
Node.js worker_thread with a clean vm.createContext() global scope.
No require, no process, no filesystem — only the approved
thetazero.* host API and safe JS built-ins.
CPU time is enforced by a parent-side kill timer; memory is capped via worker
resourceLimits. Every host function call is recorded in a structured audit trail.
vm.createContext() exposes only approved globals: JSON, Math, Date, standard constructors, and the thetazero bridge. require, process, and Buffer are denied.thetazero.* call is logged with function name, argument summary, timestamp, allow/deny decision, and duration. Returned in every execution response.memory_limit_mb (default 128 MB), cpu_time_limit_ms (default 30 s), and max_api_calls_per_run (default 50).// Execution response includes full resource telemetry { "execution_id": 4821, "status": "completed", "output": { "summary": "..." }, "resource_usage": { "cpu_ms": 1842, "memory_mb": 128, "api_calls": 3, "host_calls": 5 }, "host_call_audit": [ { "fn": "http_request", "allowed": true, "duration_ms": 412 }, { "fn": "write_result", "allowed": true, "duration_ms": 0 } ], "violation_count": 0, "was_terminated": false }
Host API — thetazero.*
Agent code running inside the sandbox communicates with the outside world exclusively through the
thetazero host bridge. All calls are async and return Promises.
Use thetazero.* (or alias it to const tz = thetazero) inside your agent's entry_code.
These functions are NOT available in the Python SDK — they run inside the sandbox at execution time.
| Function | Description | Config required |
|---|---|---|
thetazero.log(msg, level?) |
Emit a structured log entry. Level: 'info' (default), 'warn', 'error', 'debug'. Synchronous — no parent round-trip. |
— |
thetazero.http_request(url, method?, headers?, body?) |
Make an outbound HTTPS request. Returns { status, headers, body }. HTTPS only. Counted against max_api_calls_per_run. |
allow_network: true |
thetazero.read_context(key) |
Read a value from the agent's scoped context store. Returns null if not set. Counted against max_api_calls_per_run. |
— |
thetazero.write_result(output) |
Write the agent's final execution result. Must be JSON-serializable. Can be called multiple times — last call wins. Prefer returning a value from the entry code directly. | — |
thetazero.agentName |
Read-only. Name of the running agent. | — |
thetazero.agentVersion |
Read-only. Version string of the running agent. | — |
thetazero.executionId |
Read-only. Numeric ID of this execution record. | — |
// entry_code example — full host API usage const tz = thetazero; // Structured logging await tz.log("Starting execution", "info"); await tz.log(`Agent: ${tz.agentName} v${tz.agentVersion}`); // Outbound HTTPS (requires allow_network: true) const resp = await tz.http_request( "https://api.example.com/data", "GET", { "Authorization": "Bearer token" } ); await tz.log(`Status: ${resp.status}`); // Context store const prevCount = await tz.read_context("run_count") ?? 0; // Final result — write_result() or return value both work await tz.write_result({ processed: resp.body.items.length, run_number: prevCount + 1, });
REST API — /api/v1/sdk/agents
All endpoints require an API key with the agents scope.
Set the Authorization: Bearer tzk_… header on every request.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/sdk/agents | Register / upsert an agent by name |
| GET | /api/v1/sdk/agents | List agents for this API key |
| GET | /api/v1/sdk/agents/:id | Get one agent by ID |
| PATCH | /api/v1/sdk/agents/:id | Update code, config, or status |
| DELETE | /api/v1/sdk/agents/:id | Delete agent and all executions |
| POST | /api/v1/sdk/agents/:id/execute | Execute agent in sandbox (synchronous) |
| GET | /api/v1/sdk/agents/:id/executions | List execution history |
| GET | /api/v1/sdk/agents/:id/executions/:eid | Full execution details incl. logs & audit |
# Register a new agent (or upsert by name) curl -X POST https://thetazero.app/api/v1/sdk/agents \ -H "Authorization: Bearer tzk_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "my-summarizer", "version": "1.0.0", "entry_code": "await thetazero.write_result({ ok: true });", "config": { "memory_limit_mb": 128, "cpu_time_limit_ms": 15000, "max_api_calls_per_run": 10, "allow_network": false }, "status": "ready" }' # Response { "success": true, "agent": { "id": 42, "name": "my-summarizer", "version": "1.0.0", "status": "ready", "config": { "memory_limit_mb": 128, "cpu_time_limit_ms": 15000, "allow_network": false } } }
Python SDK
Zero-dependency Python wrapper for the ThetaZero REST API. Requires Python ≥ 3.8. Install from the sdk-package directory or pip (coming soon).
# Install (pip coming soon — use directly from source for now) pip install thetazero-sdk # Or from source pip install ./sdk-package/thetazero
from thetazero import SecureAgent agent = SecureAgent( api_key="tzk_your_api_key", # or set THETAZERO_API_KEY env var name="hello-world", description="Simplest possible SDK agent", ) # Deploy with raw JavaScript entry code agent.deploy( entry_code=""" await thetazero.log("Hello from the sandbox!"); await thetazero.write_result({ message: "Hello, " + (input.name || "world") + "!" }); """ ) # Run it result = agent.run(input={"name": "Alice"}) result.raise_for_status() # raises RuntimeError if status != completed print(result.output) # {'message': 'Hello, Alice!'} print(result.resource_usage) # {'cpu_ms': 18, 'api_calls': 0, 'host_calls': 2} # List executions for ex in agent.executions(): print(ex["status"], ex["resource_usage"])
SecureAgent methods
| Method | Description |
|---|---|
deploy(entry_code?, **kwargs) | Register / upsert the agent on ThetaZero. Returns the agent record. |
run(input?) | Execute in the sandbox synchronously. Returns ExecutionResult. |
executions(page?, limit?, status?) | List execution history. Returns list of dicts. |
get_execution(execution_id) | Full execution detail including logs and audit trail. |
get_agent() | Retrieve the current agent definition. |
list_agents() | List all agents for this API key. |
update(**kwargs) | Patch agent fields (entry_code, config, status, etc.). |
delete() | Permanently delete the agent and all executions. |
AgentConfig fields
| Field | Type | Default | Description |
|---|---|---|---|
memory_limit_mb | int | 128 | Worker thread memory cap (MB) |
cpu_time_limit_ms | int | 30 000 | Wall-clock execution timeout (ms) |
max_api_calls_per_run | int | 50 | Max http_request / read_context calls |
allow_network | bool | False | Enable outbound HTTPS |
allow_filesystem | bool | False | Enable filesystem access (reserved) |
sandbox_template | str | "STANDARD" | STRICT / STANDARD / DEV |
allowed_domains | list[str] | [] | Domain allow-list for network calls (empty = all HTTPS) |
Sandboxing
Every agent runs in an isolated execution environment. Choose from three policy templates — STRICT for enterprise, STANDARD for general use, DEV for local development.
// Override specific limits within a template const agent = new SecureAgent({ sandbox: 'STRICT', limits: { maxMemoryMb: 512, // override STRICT default of 256 maxExecutionTimeSec: 180, // override STRICT default of 120 }, }); // Verify TEE attestation after execution const proof = await agent.verifyExecution(result.executionId); console.log(proof.tee_mode); // 'theta_tee' | 'docker_fallback' console.log(proof.attestation_id); // cryptographic attestation ID console.log(proof.chain_valid); // true if audit chain intact
Permission System
Deny-by-default capability model. Agents have zero permissions unless explicitly granted. Use presets or compose custom scope arrays.
The scopes listed below are the planned permission model. Today, all live API keys have full access to your account. Role-based, per-scope enforcement will be available in Q2 2026.
| Scope | Description |
|---|---|
| compute:read | Read compute job status and metrics |
| compute:write | Submit compute jobs to EdgeCloud nodes |
| inference:call | Make LLM inference API calls |
| data:read | Read structured data inputs |
| data:write | Write structured data outputs |
| network:outbound | Make outbound HTTP requests |
| storage:read | Read from persistent storage |
| storage:write | Write to persistent storage |
| agents:read | Read outputs from other agents (cross-agent) |
| agents:write | Write to other agents or spawn subagents |
// Use a built-in preset permissions: SecureAgent.permissions.CODER // → ['compute:read','compute:write','inference:call','data:read','network:outbound'] // Or compose custom scopes permissions: ['inference:call', 'data:read'] // Available presets SecureAgent.permissions.READONLY // safest SecureAgent.permissions.WRITER // inference + data:read only SecureAgent.permissions.RESEARCHER // network + inference, no cross-agent write SecureAgent.permissions.CODER // network + compute + inference SecureAgent.permissions.ANALYST // broadest data access SecureAgent.permissions.FULL // all scopes — trusted agents only
Audit Trail
Every agent action is logged with a timestamp, agent ID, action type, input/output summary, and permission state. Rows are immutable (UPDATE/DELETE blocked at DB level). Batches are anchored to the blockchain every 5 minutes for tamper-evidence.
// Query the full audit log const audit = await agent.getAuditLog({ from: '2026-01-01', to: '2026-01-31', actionTypes: ['api_call', 'permission_denied'], violationsOnly: false, limit: 200, }); // → { events: [...], total: 47, anchored: true } // Verify a specific record's blockchain integrity const proof = await agent.verifyAuditRecord(12345); // → { chain_valid: true, anchor_tx_hash: '0xabc...', verified_at: '...' } // Export for compliance review const csv = await agent.exportAuditLog('csv', { from: '2026-01-01', to: '2026-03-31', });
Audit rows have a Postgres trigger that raises an exception on any UPDATE or DELETE. Not configurable. This supports SOC 2 evidence collection requirements.
Content Safety Filters
Inputs and outputs pass through a two-layer safety pipeline: fast regex pattern matching, then AI scoring for borderline cases.
| Layer | What it checks | Action on fail |
|---|---|---|
| Pattern match | Toxicity, injection, harmful content patterns | Block immediately |
| AI scoring | Toxicity score < 0.4, injection score < 0.35 | Block + log violation |
| Resource bounds | Prompt length, cost delta vs parent, evolution rate | Block + alert |
Content safety is always on for STRICT and STANDARD sandbox templates. Can be disabled only in DEV mode.
Rate Limits & Quotas
Per-execution and per-swarm rate limits prevent runaway agents from consuming unbounded resources.
| Limit type | Default | Override |
|---|---|---|
| API calls / minute (per execution) | 60 | limits.maxApiCallsPerRun |
| Swarm executions / hour | 10 | Contact support |
| Memory per execution | 512 MB | limits.maxMemoryMb |
| Max execution time | 300 sec | limits.maxExecutionTimeSec |
Quota violations are logged to the audit trail as rate_limit_hit or sandbox_limit_hit events with is_violation: true.
Kill Switch
Instant agent termination from the SDK or dashboard. Supports per-agent and global kill with full reason logging.
// Stop a specific agent (from SDK) await agent.stop('Suspicious output detected — halting for review'); // Stop from any script (without SecureAgent instance) const res = await fetch(`/api/sdk/agents/${agentId}/kill`, { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify({ reason: 'Policy violation' }), }); // Global kill switch (stops ALL agents) await fetch('/api/sdk/kill-switch/global', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify({ halted: true, reason: 'Emergency maintenance' }), });
Controls Mapping & Evidence
One call to map controls and generate evidence for your compliance team's review. ThetaZero evaluates your agent configuration against framework requirements and produces a coverage report. Output is audit-prepared evidence — not a certification or compliance score.
// Apply compliance frameworks at configure() time const agent = new SecureAgent({ compliance: ['eu_ai_act', 'soc2', 'nist_ai_rmf'], }); await agent.configure(); // evaluates immediately // Get current compliance status const status = await agent.getComplianceStatus(); // Generate evidence package for compliance team review const evidence = await agent.getEvidencePackage('eu_ai_act', 'markdown'); // → controls-mapped evidence document — audit-prepared, not a certification // Export full compliance coverage report (JSON) const report = await agent.exportComplianceReport('json');
API Reference
new SecureAgent(opts)
Constructor options.
Permission Requests v1.1
Agents declare elevated permissions upfront. The account owner reviews and approves or denies before execution proceeds. Deny-by-default — nothing is granted unless explicitly requested and approved.
SDKError with code PERMISSION_DENIED, PERMISSION_EXPIRED, or PERMISSION_TIMEOUT on rejection.
// Agent requests network + external API access before execution
await agent.requestPermission({
permissions: {
allow_network: true,
allow_external_apis: true,
max_api_calls_per_run: 500,
},
justification: 'Needs to call OpenWeatherMap for forecast data',
timeoutMs: 120_000, // 2 min
});
// If we get here, the owner approved — safe to proceed
const result = await agent.run({ task: 'Fetch weather forecast for NYC' });
Pending requests appear in Security → Permission Requests in the ThetaZero dashboard. A red badge shows the count of unreviewed requests. Owners receive real-time notifications. Each request shows the permissions sought, the agent type, and the justification provided.
| Method | Endpoint | Description |
|---|---|---|
POST | /api/sdk/permission-requests | Create a permission request |
GET | /api/sdk/permission-requests?status=pending | List requests by status |
POST | /api/sdk/permission-requests/:id/approve | Approve a pending request |
POST | /api/sdk/permission-requests/:id/deny | Deny a pending request |
Live Audit Stream v1.1
Subscribe to a real-time stream of agent actions via Server-Sent Events (SSE). Every action — API calls, file access, inference calls, permission checks — appears in the stream as it happens.
onEvent(type, data) for each audit event.
Returns a handle with a close() method to disconnect. Works in Node.js ≥18.
For browsers, use new EventSource('/api/sdk/audit/stream') directly.
// Node.js — watch a live execution
const stream = agent.streamAuditLog(
{ executionId: 1234 },
(type, data) => {
if (type === 'audit') {
console.log(`[${data.action_category}] ${data.description}`);
if (data.is_violation) console.error('⚠ VIOLATION:', data.description);
}
}
);
// Run the agent (stream will receive events in real time)
await agent.run({ task: 'Analyze Q1 metrics and generate report' });
// Disconnect when done
stream.close();
executionId, agentId, since (ISO timestamp).
Events: connected on open, audit per action, timeout at 10-min limit, keepalive every 15s.
// Browser — watch all events for your account
const source = new EventSource(
'/api/sdk/audit/stream?executionId=1234',
{ headers: { Authorization: 'Bearer tzk_...' } }
);
source.addEventListener('audit', (e) => {
const action = JSON.parse(e.data);
console.log(action.action_type, action.description);
});
source.addEventListener('timeout', () => source.close());
Start in 2 minutes
Get an API key, install the SDK, and ship your first governed agent today.