Skip to main content

sofias-sdk-lite

Build multi-node agents on a declarative graph and run them against RabbitMQ.

sofias-sdk-lite gives you:

  • An agent graph — LLM nodes, function nodes, delegation nodes (agent-to-agent), aggregator nodes (fan-in), and planner nodes (dynamic DAGs), wired together with explicit routing strategies.
  • A messaging layer — pydantic wire models (AgentTaskMessage, StreamFragment, delegation contracts) and a RabbitMQ transport (client, consumer, publisher, RPC, delegation transport) built on aio-pika and RabbitMQ Streams.
  • A runner — AgentRunner consumes tasks from a queue, resolves per-request settings, executes your agent, and streams the response back — with graceful shutdown, retries, and circuit breakers built in.
  • An LLM that is already wired — LLM nodes talk to the Sofias Bifrost gateway (or any OpenAI-compatible endpoint) using the model, URL and key from the agent's settings or the SOFIAS_LLM_* environment. create_llm() builds the client when you need it explicitly; LLMCallable stays a protocol for anything the bundled clients do not cover.

Nothing here depends on a private backend or an internal config service. Where the model lives is deployment configuration, not agent code.

Install

pip install sofias-sdk-lite
# or
uv add sofias-sdk-lite

Requires Python 3.11+ and a running RabbitMQ broker (with the Streams plugin enabled) if you use the runner or streaming responses.

Quickstart

A minimal agent with a single function node:

import asyncio

from sofias_sdk_lite import (
    AgentBuilder,
    AgentMessage,
    BaseAgentSettings,
    InputContract,
    NodeContract,
    OutputContract,
)


class GreetInput(InputContract):
    name: str


class GreetOutput(OutputContract):
    greeting: str


class HelloSettings(BaseAgentSettings):
    pass


def greet(data: dict, context: dict | None = None) -> dict:
    return {"greeting": f"Hello, {data['name']}!"}


async def main() -> None:
    contract = NodeContract(input_schema=GreetInput, output_schema=GreetOutput)
    agent = (
        AgentBuilder("hello_agent", version="0.1.0")
        .with_settings_class(HelloSettings)
        .with_contract(input_schema=GreetInput, output_schema=GreetOutput)
        .add_function_node("greeter", contract, process_fn=greet)
        .set_entry_node("greeter")
        .set_terminal("greeter")
        .build()
    )

    response = await agent.execute(AgentMessage(content=GreetInput(name="World")))
    print(response.content)  # {"greeting": "Hello, World!"}


asyncio.run(main())

See examples/ for a runner against a local RabbitMQ (docker-compose.yml included), tool loops, streaming, and agent-to-agent delegation.

Connecting to the LLM

An agent declares what the model should do; where the model lives is resolved at build():

  1. Under AgentRunner, from the per-task settings the platform sends (model_name, router_url, router_api_key on BaseAgentSettings).
  2. Otherwise from the environment: SOFIAS_LLM_MODEL, SOFIAS_LLM_BASE_URL (default http://bifrost:8080/v1), SOFIAS_LLM_API_KEY, SOFIAS_LLM_PROVIDER (default bifrost). The BIFROST_MODEL / BIFROST_BASE_URL / BIFROST_API_KEY variables the Sofias Developer Portal injects into agent containers are accepted as fallbacks, so a portal-deployed agent needs no LLM configuration at all.
  3. Or explicitly: .with_llm(create_llm(model="default", api_key=...)).
from sofias_sdk_lite import AgentBuilder, LLMNodeConfig, NodeContract

agent = (
    AgentBuilder("qa_agent")
    .with_settings_class(MySettings)
    .with_contract(input_schema=Question, output_schema=Answer)
    .add_llm_node(
        "answerer",
        LLMNodeConfig(name="answerer", input_contract=Question, output_contract=Answer,
                      system_prompt="Answer in one sentence."),
        NodeContract(input_schema=Question, output_schema=Answer),
    )
    .set_entry_node("answerer")
    .set_terminal("answerer")
    .build()          # no LLM client anywhere in this file
)

See examples/03_llm_agent.py and the LLM integration guide (streaming, retries, bringing your own client).

Running an agent against RabbitMQ

from sofias_sdk_lite import AgentRunner, RunnerConfig, RabbitMQConfig, AgentMessage


class MyAgentRunner(AgentRunner):
    settings_class = MySettings

    def build_agent(self, settings, workflow):
        return (
            AgentBuilder("my_agent")
            .with_settings_class(type(settings))
            .with_response_workflow(workflow)
            # ... nodes, routing ...
            .build()
        )

    def prepare_input(self, task, history, role):
        return AgentMessage(
            content=MyInput(message=task.content, role=role),
            conversation_id=task.conversation_id,
        )


if __name__ == "__main__":
    MyAgentRunner(
        RunnerConfig(
            queue="my-agent-tasks",
            agent_name="my_agent",
            rabbitmq=RabbitMQConfig(host="localhost"),
        )
    ).run()

Optional extras

  • sofias-sdk-lite[otel] — installs opentelemetry-api so the runner opens an agent.handle span per turn and response fragments carry the active span's traceparent. Without it, the inbound traceparent is still echoed end to end.

Scope (v1)

Core agent graph, RabbitMQ messaging, the runner, and LLM clients for the Bifrost gateway / any OpenAI-compatible endpoint ship today. Memory and MCP tool discovery are intentionally out of scope for v1 — the SDK ships the relevant protocols (MemoryProvider, ToolProvider) so you can plug in your own, and these become optional extras in a later release.

License

Apache-2.0. See LICENSE.

Release files for sofias-sdk-lite 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sofias-sdk-lite 0.1.4
File Size Uploaded
sofias_sdk_lite-0.1.4.tar.gz 146.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sofias-sdk-lite 0.1.4
File Interpreter ABI Platform
sofias_sdk_lite-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 335.9 kB

Release files / sofias_sdk_lite-0.1.4.tar.gz

Download URL sofias_sdk_lite-0.1.4.tar.gz
Size 146.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8861bf42cdaf835ea10eadb79181b93097dc92428d3305e2f88d8bebd1d0e470
BLAKE2b-256 checksum
How to use checksums
5dbc70f4d49e73a9a9bdc0eb8cddfeb733cd0566c3368e53f79739bc540f4b8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / sofias_sdk_lite-0.1.4-py3-none-any.whl

Download URL sofias_sdk_lite-0.1.4-py3-none-any.whl
Size 189.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
471b0dec9f3409f25ff289fd2959873208b1101840714fc969d8b73ded909065
BLAKE2b-256 checksum
How to use checksums
b523243c1a10971c504bd5b8ded6891363821840267cf5cebc509843cefc2f34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.1.5

2 release files

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page