Testing your agent
The graph runs entirely in-process — testing an agent doesn't require a broker or a real LLM.
Testing the graph without a broker
import pytest
from sofias_sdk_lite import AgentMessage
@pytest.mark.asyncio
async def test_my_agent_greets():
agent = build_my_agent() # your AgentBuilder(...).build()
response = await agent.execute(AgentMessage(content=MyInput(name="World")))
assert response.status.value == "success"
assert response.content == {"greeting": "Hello, World!"}
Faking the LLM
Implement LLMCallable with canned responses instead of calling a real
provider:
from sofias_sdk_lite.llm import LLMCallable, LLMResponse
class FakeLLM:
def __init__(self, responses: list[LLMResponse]):
self._responses = iter(responses)
async def invoke(self, prompt, tools=None, messages=None, system_prompt=None, response_format=None):
return next(self._responses)
builder.with_llm(FakeLLM([LLMResponse(content="canned answer")]))
When the builder lives inside an AgentRunner.build_agent() you do not want
to edit, install the fake as the default LLM around the build instead, or
override the runner's create_llm() hook:
from sofias_sdk_lite import default_llm
with default_llm(FakeLLM([LLMResponse(content="canned answer")])):
agent = runner.build_agent(settings, workflow)
class TestRunner(MyRunner):
def create_llm(self, settings):
return FakeLLM([LLMResponse(content="canned answer")])
Testing without RabbitMQ
Use NullWorkflow in place of ChatResponseWorkflow — it records what was
sent instead of publishing anywhere:
from sofias_sdk_lite import NullWorkflow
workflow = NullWorkflow()
builder.with_response_workflow(workflow)
agent = builder.build()
await agent.execute(message)
assert len(workflow.responses) == 1
For delegation, use NullDelegationTransport the same way — it stores
requests and lets you inject simulated responses without a broker.
Testing an AgentRunner
The runner's _handle_message() is exercised indirectly by feeding it a
MessageContext built from a plain AgentTaskMessage and a fake
RabbitMQClient/consumer — or, more simply, unit test build_agent() and
prepare_input() directly (they're plain methods, not tied to RabbitMQ) and
rely on integration tests against a local broker (see
examples/docker-compose.yml) for the wiring itself.