Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Python Testing

The Python SDK is designed so application tests can run without network access. Use deterministic model helpers and Python tool callbacks to cover runtime composition, tool loops, output validation, HITL, sessions, and streams.

TestModel

TestModel.text(...) returns one final text response:

from starweaver import create_agent
from starweaver.testing import TestModel


async def test_ready() -> None:
    result = await create_agent(model=TestModel.text("ready")).run("status")
    assert result.output == "ready"

Use response scripts for multi-turn loops:

from starweaver import create_agent, tool
from starweaver.testing import TestModel


@tool
async def echo(value: str) -> dict[str, str]:
    return {"value": value}


async def test_tool_loop() -> None:
    model = TestModel.responses(
        [
            TestModel.tool_call_response(
                [{"id": "call_echo", "name": "echo", "arguments": {"value": "hi"}}]
            ),
            {"text": "done"},
        ]
    )
    result = await create_agent(model=model, tools=[echo]).run("use echo")
    assert result.output == "done"

FunctionModel

Use FunctionModel when the test needs to inspect prepared request params or branch on message history:

from starweaver import create_agent, tool
from starweaver.testing import FunctionModel


@tool
async def echo(value: str) -> dict[str, str]:
    return {"value": value}


def respond(messages: list[object], info: dict[str, object]) -> dict[str, object]:
    params = info["params"]
    assert isinstance(params, dict)
    assert params["tools"][0]["name"] == "echo"
    if len(messages) == 1:
        return {"tool_calls": [{"id": "call_echo", "name": "echo", "arguments": {"value": "hi"}}]}
    return {"text": "done"}


async def test_function_model() -> None:
    model = FunctionModel(respond)
    result = await create_agent(model=model, tools=[echo]).run("use echo")
    assert result.output == "done"
    assert model.captured_messages()

Streams In Tests

Stream tests can assert record order without a provider:

from starweaver import create_agent
from starweaver.testing import TestModel


async def test_stream_records() -> None:
    agent = create_agent(model=TestModel.text("streamed"))
    events = [event async for event in agent.run_stream("stream")]
    assert events[0].kind == "run_start"
    assert events[-1].kind == "run_complete"

Use StreamAdapter to project collected events into text, tool events, usage snapshots, or sideband records.

Local Gates

Run the full Python package gate from the repository root:

make py-check

For focused iteration:

make py-lint
make py-rust-check
make py-test

For docs changes:

make docs-check
make docs-build