Skip to main content

Operator Architecture

Framework-agnostic multi-agent orchestration SDK.

Operator Architecture (OA) manages state, context, sub-agents, and orchestration. It does not call LLMs, run tool loops, or ship coding tools. You plug in any agent runtime — Relay, LangChain, OpenAI Agents, HTTP services, or a plain async function.

For the earlier coding-CLI / five-pillars vision, see ORIGINAL_CONCEPT.md.

Install

pip install -e .
# or
uv pip install -e .

Runtime dependencies: none (stdlib only).

from operator_architecture import (
    StateMachine,
    Coordinator,
    AgentSpec,
    AgentRequest,
    AgentResult,
    callable_agent,
)

What OA owns vs what you own

Operator Architecture Your host
StateMachine, Coordinator, AgentSpec Agent implementations (AgentRunner)
OpenAI-compatible message threads Relay / LangChain / custom loops
commission → stage → accept / instruct Models, API keys, tools, MCP, FS
Optional streaming_callback fan-in Emitting stream events from runners

Core objects

AgentSpec + AgentRunner

Register any number of sub-agents. Each needs a runner OA will call:

async def research(request: AgentRequest) -> AgentResult:
    # call Relay, LangChain, HTTP, … — OA does not care
    return AgentResult(content=f"Findings for: {request.objective}")

researcher = AgentSpec(
    name="researcher",
    description="Read-only exploration",
    skill="You are a careful researcher. Answer with concrete findings.",
    runner=callable_agent(research),
    model="my-model",  # metadata only
)

Protocol:

class AgentRunner(Protocol):
    async def run(
        self,
        request: AgentRequest,
        *,
        streaming_callback: StreamingCallback = None,
    ) -> AgentResult: ...

AgentRequest carries OpenAI-shaped messages, objective, skill, optional checklist / agent_props.
AgentResult.content is staged as agent_message.

Coordinator

Owns the user-facing skill string and optional runner for sm.run():

coordinator = Coordinator(
    skill="You operate the state machine…",  # default skill provided
    runner=my_coordinator_runner,            # optional
    model="coord-model",
)

StateMachine

sm = StateMachine(coordinator=coordinator, agents=[researcher])

No process-global singleton — hold the instance yourself (sm = StateMachine(...)).

Lifecycle

user → (optional) sm.run / host
     → commission(agent, objective)
         → AgentRunner.run(AgentRequest)
         → stage agent_message  (status=staged)
     → accept_agent_result(agent, index)   # compact result for core thread
        or instruct_agent(agent, index, message)  # continue junior

Direct API (always available)

staged = await sm.commission("researcher", "Find all uses of vLLM")
msg = sm.get_agent_message("researcher", 1)
accepted = sm.accept("researcher", 1)          # or accept_agent_result
# or:
await sm.instruct("researcher", 1, "Also check Dockerfiles")

sm.list_agents()
sm.list_objectives()

Indexed access: sm.agent("researcher")[1].agent_message.

sm.run (optional)

If Coordinator.runner is set, await sm.run(user_text, streaming_callback=...) appends the user message and invokes that runner with:

  • metadata["tools"] — orchestration callables
  • metadata["tool_schemas"] — OpenAI tools[] schemas

OA does not execute a tool loop. Your runner (Relay, LangChain, …) must invoke those callables when the model requests them.

tools = sm.orchestration_tools()
# list_agents, commission, get_agent_message,
# accept_agent_result, instruct_agent, list_objectives

OpenAI-compatible context

Coordinator and junior threads are lists of chat.completions-style dicts:

{"role": "system"|"user"|"assistant"|"tool", "content": "...", ...}

Helpers: Messages (.system(), .user(), .assistant(), .to_list()).

streaming_callback

Optional observability hook (UI, logs, websockets). Sync or async:

async def on_stream(event: dict) -> None:
    print(event["phase"], event.get("detail", "")[:80])

await sm.commission("researcher", "…", streaming_callback=on_stream)
# or
await sm.run("…", streaming_callback=on_stream)

Phases: start, token, tool_start, tool_result, tool_error, commissioned, done, fail.
Runners may emit events; OA forwards them and also emits lifecycle events around commission.

Writing adapters

Adapter idea Wraps
callable_agent(fn) Plain async/sync function (shipped)
Relay agent encode.relay_async / courier_os.relay inside run()
LangChain agent AgentExecutor / LangGraph; map messages ↔ LC messages
HTTP agent POST OpenAI-compatible or custom JSON API

OA never imports those libraries. Keep adapters in your host.

Minimal Relay sketch (host code)

class RelayRunner:
    def __init__(self, model, api_key, base_url, tools):
        self.model, self.api_key, self.base_url, self.tools = model, api_key, base_url, tools

    async def run(self, request, *, streaming_callback=None):
        import encode
        messages = encode.Messages()
        for m in request.messages:
            # map dicts into encode.Messages as needed
            ...
        out = await encode.relay_async(
            model=self.model,
            api_key=self.api_key,
            base_url=self.base_url,
            messages=messages,
            tools=self.tools or request.metadata.get("tools"),
        )
        return AgentResult(content=out.content or "", raw=out)

Example

See examples/minimal_callable.py.

Design boundaries

  • Not a coding CLI or competitor to Cursor/Claude Code
  • Not an inference or tool-loop SDK (use Courier OS, encode, agentloop, LangChain, …)
  • Not coupled to AXE or Courier OS — hosts may wrap them as runners

License / status

Early SDK (0.2.0). API may evolve; the orchestration contract (commission / stage / accept) is the stable idea.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

operator_architecture-0.2.0.tar.gz (24.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

operator_architecture-0.2.0-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file operator_architecture-0.2.0.tar.gz.

File metadata

  • Download URL: operator_architecture-0.2.0.tar.gz
  • Upload date:
  • Size: 24.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for operator_architecture-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c79ff5679ad585ac04f8784fa2ce4e4dbb1bbc2f3c71c5362c09292ec43daa6b
MD5 d05320f8e31ec5a711ac9baacfdff95f
BLAKE2b-256 9dacaf85613ff3938a1e7d5a71f70e0cc986f305eb157d18c4d138f9e9b2494a

See more details on using hashes here.

File details

Details for the file operator_architecture-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: operator_architecture-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for operator_architecture-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5e54db4a354d05d016a5ce071c5aa7bb9b40293dab891b00bd1534fe46aa74b2
MD5 09577a8c1133b8a6299e04de032d6b44
BLAKE2b-256 e4da10e0dec45d313ff4df5883a07390a676c9cd9f8a3883c4a2b7c3de4e7adb

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.0

2 files

0.2.2

2 files

0.2.1

2 files

This release

0.2.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page