Python SDK
AegisClient async HTTP client and bootstrap.py Dispatch Protocol types for Python agent authors.
Python SDK
Install the AEGIS Python SDK:
pip install aegis-sdkThe SDK consists of two distinct layers:
AegisClient— async HTTP client: start executions, manage approvals, invoke SEAL tools, administer tenants and rate limitsbootstrap.py/ Dispatch Protocol types — agent-side: the wire format exchanged between a custom bootstrap script and the orchestrator's/v1/dispatch-gateway
AegisClient
from aegis import AegisClient
async with AegisClient(
base_url="https://your-aegis-node",
api_key="your-keycloak-jwt", # Optional; alternatively set AEGIS_API_KEY env var
) as client:
resp = await client.start_execution("agt-uuid", "Write a primality check in Python")
print(resp.execution_id)Method Reference
| Section | Method | Description |
|---|---|---|
| Execution | start_execution(agent_id, input, context_overrides?) | Start an agent execution |
| Execution | stream_execution(execution_id, token?) | Stream execution events (SSE) |
| Human Approvals | list_pending_approvals() | List all pending human-in-the-loop approvals |
| Human Approvals | get_pending_approval(approval_id) | Get a single pending approval |
| Human Approvals | approve_request(approval_id, feedback?, approved_by?) | Approve a pending request |
| Human Approvals | reject_request(approval_id, reason, rejected_by?) | Reject a pending request |
| SEAL | attest_seal(payload) | Obtain an SEAL security attestation token |
| SEAL | invoke_seal(payload) | Invoke an SEAL tool |
| SEAL | list_seal_tools(security_context?) | List available SEAL tools |
| Dispatch Gateway | dispatch_gateway(payload) | Send a dispatch gateway request |
| Stimulus | ingest_stimulus(payload) | Ingest a stimulus event |
| Stimulus | send_webhook(source, payload) | Send a webhook stimulus |
| Workflow Logs | get_workflow_execution_logs(execution_id, limit?, offset?) | Fetch paginated workflow logs |
| Workflow Logs | stream_workflow_execution_logs(execution_id) | Stream workflow logs (SSE) |
| Admin: Tenants | create_tenant(slug, display_name, tier?) | Create a new tenant |
| Admin: Tenants | list_tenants() | List all tenants |
| Admin: Tenants | suspend_tenant(slug) | Suspend a tenant |
| Admin: Tenants | delete_tenant(slug) | Delete a tenant |
| Admin: Rate Limits | list_rate_limit_overrides(tenant_id?, user_id?) | List rate limit overrides |
| Admin: Rate Limits | create_rate_limit_override(payload) | Create a rate limit override |
| Admin: Rate Limits | delete_rate_limit_override(override_id) | Delete a rate limit override |
| Admin: Rate Limits | get_rate_limit_usage(scope_type, scope_id) | Get rate limit usage records |
| Health | health_live() | Liveness probe |
| Health | health_ready() | Readiness probe |
Execution
start_execution(agent_id, input, context_overrides?)
Start an agent execution and receive an execution ID for streaming.
async with AegisClient("https://your-aegis-node", api_key=TOKEN) as client:
resp = await client.start_execution(
agent_id="agt-uuid",
input="Write a primality check in Python",
)
print(resp.execution_id) # "exec-uuid"Parameters:
| Name | Type | Description |
|---|---|---|
agent_id | str | UUID of a deployed agent |
input | str | Task prompt for the agent |
context_overrides | Any | Optional context overrides |
Returns: StartExecutionResponse with execution_id: str.
stream_execution(execution_id, token?)
Stream real-time execution events via SSE. Returns an async generator.
async with AegisClient("https://your-aegis-node", api_key=TOKEN) as client:
resp = await client.start_execution("agt-uuid", "Solve the task")
async for event in client.stream_execution(resp.execution_id):
print(f"[{event.event_type}] {event.data}")Parameters:
| Name | Type | Description |
|---|---|---|
execution_id | str | UUID from start_execution |
token | str | Optional auth token override |
Returns: AsyncGenerator[ExecutionEvent, None] — each event has event_type: str and data: Dict[str, Any].
Human Approvals
list_pending_approvals()
List all pending human-in-the-loop approval requests.
approvals = await client.list_pending_approvals()
for a in approvals:
print(f"{a.id}: {a.prompt} (timeout: {a.timeout_seconds}s)")Returns: List[PendingApproval] — each with id, execution_id, prompt, created_at, timeout_seconds.
get_pending_approval(approval_id)
Fetch a single pending approval by ID.
Returns: PendingApproval.
approve_request(approval_id, feedback?, approved_by?)
Approve a pending request, optionally with feedback.
resp = await client.approve_request(
approval_id="approval-uuid",
feedback="Looks good, proceed.",
approved_by="jeshua@100monkeys.ai",
)
print(resp.status) # "approved"Returns: ApprovalResponse with status: str.
reject_request(approval_id, reason, rejected_by?)
Reject a pending request with a mandatory reason.
Returns: ApprovalResponse with status: str.
SEAL
attest_seal(payload)
Obtain a security attestation token for SEAL tool invocation.
Returns: SealAttestationResponse with security_token: str.
invoke_seal(payload)
Invoke an SEAL tool with an attested payload.
Returns: Dict[str, Any] — tool-specific response.
list_seal_tools(security_context?)
List available SEAL tools, optionally filtered by security context.
Returns: SealToolsResponse with protocol, attestation_endpoint, invoke_endpoint, security_context, and tools: List[Any].
Dispatch Gateway
dispatch_gateway(payload)
Send a raw dispatch gateway request. Used by custom bootstrap scripts.
Returns: Dict[str, Any].
Stimulus
ingest_stimulus(payload)
Ingest a stimulus event into the stimulus-response pipeline.
Returns: Dict[str, Any].
send_webhook(source, payload)
Send a webhook-style stimulus from an external source.
Returns: Dict[str, Any].
Workflow Logs
get_workflow_execution_logs(execution_id, limit?, offset?)
Fetch paginated workflow execution logs.
Returns: WorkflowExecutionLogs with execution_id, events: List[Any], count, limit, offset.
stream_workflow_execution_logs(execution_id)
Stream workflow execution logs in real time via SSE.
Returns: AsyncGenerator[ExecutionEvent, None].
Admin: Tenant Management
create_tenant(slug, display_name, tier?)
Create a new tenant. Defaults to "enterprise" tier.
Returns: Tenant with slug, display_name, status, tier, keycloak_realm, openbao_namespace, quotas, created_at, updated_at.
list_tenants()
List all tenants.
Returns: List[Tenant].
suspend_tenant(slug) / delete_tenant(slug)
Suspend or delete a tenant by slug.
Returns: Dict[str, str].
Admin: Rate Limits
list_rate_limit_overrides(tenant_id?, user_id?)
List rate limit overrides, optionally filtered by tenant or user.
Returns: List[RateLimitOverride] with id, resource_type, bucket, limit_value, tenant_id, user_id, burst_value, created_at, updated_at.
create_rate_limit_override(payload)
Create a rate limit override.
Returns: RateLimitOverride.
delete_rate_limit_override(override_id)
Delete a rate limit override.
Returns: Dict[str, str].
get_rate_limit_usage(scope_type, scope_id)
Get rate limit usage records for a given scope.
Returns: List[UsageRecord] with scope_type, scope_id, resource_type, bucket, window_start, counter.
Health
health_live() / health_ready()
Liveness and readiness probes.
Returns: Dict[str, str].
SEAL Protocol
The aegis.seal subpackage provides low-level cryptographic primitives and client utilities for workloads that need to self-attest and call SEAL tools directly — without going through AegisClient. Useful for custom bootstrap scripts and server-side envelope verification.
Import paths
from aegis.seal import SEALClient, Ed25519Key
from aegis.seal.envelope import create_seal_envelope, verify_seal_envelope, create_canonical_messageSEALClient
A high-level client that handles key generation, attestation, and tool invocation in one object.
from aegis.seal import SEALClient
client = SEALClient(
gateway_url="https://your-aegis-node",
workload_id="my-workload",
security_scope="default",
)
try:
result = await client.attest()
print(result.security_token)
output = await client.call_tool("read_file", {"path": "/workspace/main.py"})
print(output)
finally:
client.erase() # zeroes the in-memory private keyConstructor:
SEALClient(gateway_url: str, workload_id: str, security_scope: str)| Parameter | Type | Description |
|---|---|---|
gateway_url | str | Base URL of the SEAL gateway |
workload_id | str | Identifier for this workload |
security_scope | str | Security context / scope label |
Methods:
| Method | Returns | Description |
|---|---|---|
await attest() | AttestationResult | Generates an Ed25519 keypair, attests to the gateway, returns a security token |
await call_tool(tool_name, arguments) | Dict[str, Any] | Calls a SEAL tool after attestation |
erase() | None | Zeroes the private key from memory |
AttestationResult:
| Field | Type | Description |
|---|---|---|
security_token | str | Bearer token for SEAL tool invocations |
expires_at | str | ISO-8601 expiry timestamp |
session_id | str | None | Optional session identifier |
Ed25519Key
Low-level Ed25519 keypair for manual envelope construction.
from aegis.seal import Ed25519Key
key = Ed25519Key.generate()
signature_b64 = key.sign_base64(b"my message")
pub_key_b64 = key.get_public_key_base64()
key.erase() # zero the private key when done| Method | Returns | Description |
|---|---|---|
Ed25519Key.generate() | Ed25519Key | Generate a new random keypair |
sign(message: bytes) | bytes | Sign raw bytes, return raw signature |
sign_base64(message: bytes) | str | Sign raw bytes, return base64-encoded signature |
get_public_key_bytes() | bytes | Raw 32-byte public key |
get_public_key_base64() | str | Base64-encoded public key |
erase() | None | Zeroes the private key from memory |
Envelope utilities
For server-side workloads (e.g. a gateway plugin) that need to construct or verify SEAL envelopes manually.
create_seal_envelope(security_token, mcp_payload, private_key)
Construct a signed SEAL envelope from a security token, an MCP payload dict, and an Ed25519Key.
from aegis.seal.envelope import create_seal_envelope
from aegis.seal import Ed25519Key
key = Ed25519Key.generate()
envelope = create_seal_envelope(
security_token="<token>",
mcp_payload={"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {...}},
private_key=key,
)
# envelope: Dict[str, Any] — pass to AegisClient.invoke_seal() or the raw SEAL endpointverify_seal_envelope(envelope, public_key_bytes, max_age_seconds?)
Server-side verification. Raises on invalid signature or expired timestamp.
from aegis.seal.envelope import verify_seal_envelope
payload = verify_seal_envelope(
envelope=envelope_dict,
public_key_bytes=bytes.fromhex(registered_public_key_hex),
max_age_seconds=30, # default: 30
)
# Returns the inner MCP payload Dict[str, Any] on successcreate_canonical_message(security_token, payload, timestamp_unix)
Low-level helper that produces the canonical bytes that are signed.
from aegis.seal.envelope import create_canonical_message
msg_bytes = create_canonical_message(
security_token="<token>",
payload={"jsonrpc": "2.0", ...},
timestamp_unix=1743600000,
)Agent Manifests
The aegis.manifest module provides Pydantic models and a fluent builder for constructing agent manifest YAML files programmatically.
from aegis.manifest import AgentManifestBuilder, AgentManifest, ImagePullPolicyAgentManifestBuilder
Fluent builder — the recommended API for creating manifests in code.
from aegis.manifest import AgentManifestBuilder, ImagePullPolicy
manifest = (
AgentManifestBuilder(name="my-agent", language="python", version="3.12")
.with_description("Analyses Python repos for security issues")
.with_instruction("You are a security auditor. Analyse the code and report CVEs.")
.with_execution_mode("iterative", max_iterations=15)
.with_image_pull_policy(ImagePullPolicy.IF_NOT_PRESENT)
.with_network_allow(["api.github.com", "pypi.org"])
.with_tool("read_file")
.with_tool("run_command")
.with_env("LOG_LEVEL", "debug")
.build()
)
manifest.to_yaml_file("./my-agent.yaml")Constructor:
AgentManifestBuilder(
name: str,
language: Optional[str] = None,
version: Optional[str] = None,
image: Optional[str] = None,
)Methods:
| Method | Description |
|---|---|
with_description(description) | Set the manifest description |
with_label(key, value) | Add a metadata label |
with_instruction(instruction) | Set the agent system instruction |
with_execution_mode(mode, max_iterations?) | Set "one-shot" or "iterative" mode |
with_image(image) | Set a custom Docker image (overrides language/version) |
with_image_pull_policy(policy) | Set the image pull policy (ImagePullPolicy enum) |
with_bootstrap_path(path) | Path to a custom bootstrap script inside the image |
with_network_allow(domains) | Allowlist of hostnames the agent may reach |
with_tool(tool) | Add a SEAL tool name to the agent's tool list |
with_env(key, value) | Add an environment variable |
build() | Returns a validated AgentManifest |
AgentManifest
The root manifest model. Serialises to the AEGIS agent manifest YAML format.
class AgentManifest(BaseModel):
apiVersion: str # "100monkeys.ai/v1"
kind: str # "Agent"
metadata: ManifestMetadata
spec: AgentSpecClass methods:
| Method | Description |
|---|---|
AgentManifest.from_yaml_file(path) | Load and validate a manifest from a YAML file |
manifest.to_yaml_file(path) | Serialise and write the manifest to a YAML file |
manifest.validate_manifest() | Validate the manifest; returns bool |
ImagePullPolicy
from aegis.manifest import ImagePullPolicy
ImagePullPolicy.ALWAYS # "Always"
ImagePullPolicy.IF_NOT_PRESENT # "IfNotPresent"
ImagePullPolicy.NEVER # "Never"Key manifest types
| Class | Purpose |
|---|---|
ManifestMetadata | name, version, description, tags, labels, annotations |
RuntimeConfig | language, version, image, image_pull_policy, isolation, model |
TaskConfig | instruction, prompt_template, input_data |
ExecutionStrategy | mode, max_iterations, llm_timeout_seconds, validation |
SecurityConfig | network (NetworkPolicy), filesystem (FilesystemPolicy), resources (ResourceLimits) |
AdvancedConfig | warm_pool_size, swarm_enabled, startup_script, bootstrap_path |
AgentSpec | Root spec combining all of the above |
For the full field reference, see the Agent Manifest Reference.
Dispatch Protocol Types
When writing a custom bootstrap script (spec.advanced.bootstrap_path in the agent manifest), import these types to build and parse the protocol payloads in a type-safe way.
The default bootstrap script injected by the orchestrator does not import this module — it implements the same wire format using stdlib only. These classes are for custom bootstrap authors.
GenerateMessage
Sent by bootstrap to start an inner-loop iteration:
from aegis.bootstrap import GenerateMessage
msg = GenerateMessage(
execution_id="exec-uuid",
iteration_number=1,
model_alias="default",
prompt="Task: Write a primality check\n\nInput: in Python",
messages=[],
)
import json, httpx
response = httpx.post(
f"{orchestrator_url}/v1/dispatch-gateway",
content=msg.model_dump_json(),
headers={"Content-Type": "application/json"},
)| Field | Type | Description |
|---|---|---|
execution_id | str | UUID from AEGIS_EXECUTION_ID env var |
iteration_number | int | 1-indexed iteration counter |
model_alias | str | LLM alias from AEGIS_MODEL_ALIAS env var |
prompt | str | Fully-rendered prompt for this iteration |
messages | list[dict] | Prior conversation history for continuation |
agent_id | str | Optional — from AEGIS_AGENT_ID env var |
DispatchResultMessage
Sent by bootstrap after executing a dispatched command:
from aegis.bootstrap import DispatchResultMessage
result = DispatchResultMessage(
execution_id="exec-uuid",
dispatch_id="dispatch-uuid", # echo from DispatchMessage
exit_code=0,
stdout="All tests passed.\n",
stderr="",
duration_ms=1243,
truncated=False,
)| Field | Type | Description |
|---|---|---|
execution_id | str | Same as the originating GenerateMessage |
dispatch_id | str | UUID echoed from the DispatchMessage |
exit_code | int | Process exit code. -1 for bootstrap-level errors. |
stdout | str | Captured stdout, tail-trimmed if truncated=True |
stderr | str | Captured stderr |
duration_ms | int | Wall-clock execution time |
truncated | bool | True when combined output exceeded max_output_bytes |
FinalMessage (parse from orchestrator response)
The orchestrator responds with a FinalMessage when the inner loop completes:
from aegis.bootstrap import FinalMessage
import json, httpx
response = httpx.post(orchestrator_url + "/v1/dispatch-gateway", ...)
data = response.json()
if data["type"] == "final":
final = FinalMessage.model_validate(data)
print(final.content) # LLM's final text output
print(final.tool_calls_executed) # Number of tools invokedDispatchMessage (parse from orchestrator response)
The orchestrator responds with a DispatchMessage when it wants bootstrap to run a command:
from aegis.bootstrap import DispatchMessage
if data["type"] == "dispatch":
cmd = DispatchMessage.model_validate(data)
# cmd.action == "exec"
# cmd.command == "python"
# cmd.args == ["-m", "pytest", "test_prime.py"]
# cmd.cwd == "/workspace"
# cmd.timeout_secs == 60Environment Variables (inside agent containers)
The orchestrator injects these into every agent container:
| Variable | Description |
|---|---|
AEGIS_AGENT_ID | UUID of the deployed agent |
AEGIS_EXECUTION_ID | UUID of this execution instance |
AEGIS_MODEL_ALIAS | LLM alias to use (e.g. "default", "fast") |
AEGIS_ORCHESTRATOR_URL | Internal URL for bootstrap.py callbacks |
See Also
- TypeScript SDK Reference
- Custom Runtime Agents — using a custom
bootstrap.py - REST API Reference — raw HTTP endpoints
MCP Tool Reference
Complete input and output schemas for all 61 AEGIS MCP tools — 60 built-in orchestrator tools and the Zaru-only zaru.switch_mode tool — with availability by context and Zaru conversation mode.
TypeScript SDK
AegisClient for TypeScript and Node.js — execution, approvals, SEAL, stimulus, admin, and more.