Aegis Orchestrator
Reference

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-sdk

The SDK consists of two distinct layers:

  • AegisClient — async HTTP client: start executions, manage approvals, invoke SEAL tools, administer tenants and rate limits
  • bootstrap.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

SectionMethodDescription
Executionstart_execution(agent_id, input, context_overrides?)Start an agent execution
Executionstream_execution(execution_id, token?)Stream execution events (SSE)
Human Approvalslist_pending_approvals()List all pending human-in-the-loop approvals
Human Approvalsget_pending_approval(approval_id)Get a single pending approval
Human Approvalsapprove_request(approval_id, feedback?, approved_by?)Approve a pending request
Human Approvalsreject_request(approval_id, reason, rejected_by?)Reject a pending request
SEALattest_seal(payload)Obtain an SEAL security attestation token
SEALinvoke_seal(payload)Invoke an SEAL tool
SEALlist_seal_tools(security_context?)List available SEAL tools
Dispatch Gatewaydispatch_gateway(payload)Send a dispatch gateway request
Stimulusingest_stimulus(payload)Ingest a stimulus event
Stimulussend_webhook(source, payload)Send a webhook stimulus
Workflow Logsget_workflow_execution_logs(execution_id, limit?, offset?)Fetch paginated workflow logs
Workflow Logsstream_workflow_execution_logs(execution_id)Stream workflow logs (SSE)
Admin: Tenantscreate_tenant(slug, display_name, tier?)Create a new tenant
Admin: Tenantslist_tenants()List all tenants
Admin: Tenantssuspend_tenant(slug)Suspend a tenant
Admin: Tenantsdelete_tenant(slug)Delete a tenant
Admin: Rate Limitslist_rate_limit_overrides(tenant_id?, user_id?)List rate limit overrides
Admin: Rate Limitscreate_rate_limit_override(payload)Create a rate limit override
Admin: Rate Limitsdelete_rate_limit_override(override_id)Delete a rate limit override
Admin: Rate Limitsget_rate_limit_usage(scope_type, scope_id)Get rate limit usage records
Healthhealth_live()Liveness probe
Healthhealth_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:

NameTypeDescription
agent_idstrUUID of a deployed agent
inputstrTask prompt for the agent
context_overridesAnyOptional 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:

NameTypeDescription
execution_idstrUUID from start_execution
tokenstrOptional 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_message

SEALClient

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 key

Constructor:

SEALClient(gateway_url: str, workload_id: str, security_scope: str)
ParameterTypeDescription
gateway_urlstrBase URL of the SEAL gateway
workload_idstrIdentifier for this workload
security_scopestrSecurity context / scope label

Methods:

MethodReturnsDescription
await attest()AttestationResultGenerates 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()NoneZeroes the private key from memory

AttestationResult:

FieldTypeDescription
security_tokenstrBearer token for SEAL tool invocations
expires_atstrISO-8601 expiry timestamp
session_idstr | NoneOptional 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
MethodReturnsDescription
Ed25519Key.generate()Ed25519KeyGenerate a new random keypair
sign(message: bytes)bytesSign raw bytes, return raw signature
sign_base64(message: bytes)strSign raw bytes, return base64-encoded signature
get_public_key_bytes()bytesRaw 32-byte public key
get_public_key_base64()strBase64-encoded public key
erase()NoneZeroes 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 endpoint

verify_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 success

create_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, ImagePullPolicy

AgentManifestBuilder

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:

MethodDescription
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: AgentSpec

Class methods:

MethodDescription
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

ClassPurpose
ManifestMetadataname, version, description, tags, labels, annotations
RuntimeConfiglanguage, version, image, image_pull_policy, isolation, model
TaskConfiginstruction, prompt_template, input_data
ExecutionStrategymode, max_iterations, llm_timeout_seconds, validation
SecurityConfignetwork (NetworkPolicy), filesystem (FilesystemPolicy), resources (ResourceLimits)
AdvancedConfigwarm_pool_size, swarm_enabled, startup_script, bootstrap_path
AgentSpecRoot 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"},
)
FieldTypeDescription
execution_idstrUUID from AEGIS_EXECUTION_ID env var
iteration_numberint1-indexed iteration counter
model_aliasstrLLM alias from AEGIS_MODEL_ALIAS env var
promptstrFully-rendered prompt for this iteration
messageslist[dict]Prior conversation history for continuation
agent_idstrOptional — 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,
)
FieldTypeDescription
execution_idstrSame as the originating GenerateMessage
dispatch_idstrUUID echoed from the DispatchMessage
exit_codeintProcess exit code. -1 for bootstrap-level errors.
stdoutstrCaptured stdout, tail-trimmed if truncated=True
stderrstrCaptured stderr
duration_msintWall-clock execution time
truncatedboolTrue 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 invoked

DispatchMessage (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 == 60

Environment Variables (inside agent containers)

The orchestrator injects these into every agent container:

VariableDescription
AEGIS_AGENT_IDUUID of the deployed agent
AEGIS_EXECUTION_IDUUID of this execution instance
AEGIS_MODEL_ALIASLLM alias to use (e.g. "default", "fast")
AEGIS_ORCHESTRATOR_URLInternal URL for bootstrap.py callbacks

See Also

On this page