Core Concepts¶
Labels¶
A label is a pair of tag sets attached to information.
source describes where information came from and is used for integrity checks.
visibility describes where information may flow and is used for confidentiality
checks.
Tag Sets¶
Tags are plain Python strings. Tag sets are normal Python sets. There is no built-in hierarchy or fuzzy matching.
Two sentinels are available:
ALL is frozenset({"*"}). NONE is frozenset().
Dynamic Labels¶
Tool labels can depend on actual tool-call arguments:
Callable label parameters must match declared tool parameters. The SDK resolves them before sending the analysis request.
Tool Flow Policies¶
A tool flow policy declares what information may control a tool call and what label the tool result produces.
@strahl.tool(
requires=Label(source={"user"}, visibility={"user"}),
produces=Label(source={"crm"}, visibility=lambda customer_id: {f"customer:{customer_id}"}),
)
def lookup_customer(customer_id: str) -> str:
...
requires labels the tool call and is also the default requirement for each
argument. produces labels the tool result for later turns.
Use params when arguments have different requirements:
@strahl.tool(
requires=Label(source={"assistant"}, visibility={"user"}),
params={
"customer_id": Label(source={"support-agent"}, visibility={"support-agent"}),
"message": Label(
source={"support-agent"},
visibility=lambda customer_id: {f"customer:{customer_id}"},
),
},
produces=Label(source={"support-agent"}, visibility=lambda customer_id: {f"customer:{customer_id}"}),
)
def reply_to_customer(customer_id: str, message: str) -> None:
...
Role Labels¶
Every non-tool message role in the transcript must have a static role label.
strahl.set_role_labels({
"user": Label(source={"user"}, visibility={"user"}),
"assistant": Label(source={"assistant"}, visibility={"user"}),
"system": Label(source={"system"}, visibility={"internal"}),
})
Supported roles are "system", "developer", "user", and "assistant".
How Analysis Works¶
When you call strahl.analyze(messages), the SDK:
- Converts OpenAI-style messages into a labeled trace.
- Resolves dynamic tool labels from actual tool-call arguments.
- Posts the trace and registered tool schemas to the Strahl API.
- Converts the API response into
AnalysisResult.
Call analyze() after the assistant response that requests tool calls and before
executing those tools.