Bridle
Guide

Branches

A step constrained to a single typed decision. The conditional in your if statement.

branch is a step shaped for one job: produce one decision, no tools. The default schema is bool, which makes it drop straight into an if.

Signature

from bridle import branch

branch(
    prompt: str,
    *,
    schema: type[T] = bool,
    context: Any = None,
    label: str | None = None,
) -> T

Returns a Call typed as T. Resolves on truthiness, attribute read, or bridle.resolve.

The common case: a yes/no

if branch("is the evidence sufficient?", context=sources):
    return write_brief(sources)
return gather_more(sources)

The model produces a single bool. The if resolves the call as part of evaluating the condition — no bridle.resolve needed.

Multi-way: enums and Literal

For more than two outcomes, pass an Enum or a Literal[...]:

from enum import Enum

class Verdict(Enum):
    APPROVE = "approve"
    REJECT = "reject"
    ESCALATE = "escalate"

verdict = branch("decide on this case", schema=Verdict, context=case)
match verdict:
    case Verdict.APPROVE: return approve(case)
    case Verdict.REJECT:  return reject(case)
    case Verdict.ESCALATE: return escalate(case)

Use enums when the values are referenced from elsewhere in the codebase. Use Literal[...] when the set is small and local:

from typing import Literal

priority: Literal["low", "med", "high"] = branch(
    "rank the priority",
    schema=Literal["low", "med", "high"],
    context=ticket,
)

Why not just step?

Three reasons branch exists separately.

Tools are forbidden. A decision should not need to call out — if the call needs evidence, gather it first, then branch over the result. The signature enforces this.

One-shot, no schema-retry stew. A bool is hard to get wrong. Branches almost never trip the schema-retry path.

The trace reads better. A call_kind: "branch" event signals "decision point" without you having to label it.

Pitfalls

Putting the gathering inside the branch. Don't ask branch "find sources, then decide." It cannot — branch has no tools. Run a step to produce the evidence, then a branch to read the verdict.

Using branch with a complex schema. A schema with many fields belongs in a step. branch is for one decision; if the result has structure, it isn't a branch.

Reading the result without using it as a condition. branch returns a Call. Inside an if, that's fine. Anywhere else, resolve explicitly:

verdict = bridle.resolve(branch("decide", schema=Verdict, context=case))

A complete example

import bridle
from bridle import agent, branch, step
from bridle.models.anthropic import install
from pydantic import BaseModel


class Source(BaseModel):
    url: str
    summary: str


class Brief(BaseModel):
    headline: str
    body: str


@agent(input=str, output=Brief, model="claude-sonnet-4-6")
def cautious_brief(topic: str) -> Brief:
    sources: list[Source] = bridle.resolve(step(
        "find three reputable sources",
        schema=list[Source],
        context=topic,
    ))

    if not branch("is the evidence sufficient?", context=sources):
        # Recurse with a sharper prompt instead of writing on weak ground.
        return cautious_brief(f"{topic} — find better-documented angles")

    return step("write the brief", schema=Brief, context=(topic, sources))


install()
brief = bridle.resolve(cautious_brief("the weather on Mars"))
print(brief.headline)

Next

On this page