Skip to content

yaab.tools

Typed function tools, toolsets, MCP and OpenAPI tools.

yaab.tools

Tools: typed function tools, agent-as-tool, and MCP interop.

AgentTool

Adapt an :class:~yaab.agent.Agent into a :class:~yaab.tools.base.Tool.

ToolAuth

Bases: BaseModel

Auth requirements for a tool, plus the logic to resolve a credential.

Pairs an auth_scheme with an auth_credential: declare the scheme and either a static credential or a credential_provider that yields one per call. For OAuth2, set consent_url + scopes so an unresolved credential produces an actionable consent prompt.

resolve async

resolve(ctx: RunContext, *, tool_name: str = '') -> ToolCredential

Resolve a usable credential for this call.

Resolution order:

  1. The static credential if present and not expired.
  2. The credential_provider (awaited if it returns a coroutine), which receives ctx so it can look up a per-identity token.
  3. Otherwise raise :class:ToolAuthRequired carrying the consent URL and scopes.

An expired static credential is skipped (not returned) so a stale OAuth token triggers a refresh via the provider rather than being sent.

ToolAuthRequired

Bases: YaabError

Raised when a tool needs authorization that couldn't be resolved.

Carries everything a caller or UI needs to drive an OAuth2-style consent flow and retry: the consent_url to send the user to, the requested scopes, and the tool name for context. The agent runtime renders this into a model-visible error: ... requires authorization string so the model can tell the user — see :meth:as_model_error.

as_model_error

as_model_error() -> str

Render the model-visible error: string the agent loop surfaces.

Format mirrors the rest of the toolset's error convention so the model sees a consistent, actionable message it can relay to the user.

ToolCredential

Bases: BaseModel

A resolved credential the framework injects into a tool call.

The fields are a small superset so one model covers all four schemes:

  • api_key: value is the key; header names where it rides.
  • bearer / oauth2: token is the bearer token.
  • basic: value is the username and token is the password.

expires_at (epoch seconds) lets short-lived OAuth tokens be detected as stale so :meth:ToolAuth.resolve can re-fetch a fresh one instead of sending an expired token.

is_expired

is_expired(*, now: float | None = None) -> bool

Return True if expires_at is set and in the past.

A small clock skew isn't accounted for here — providers should issue a fresh token rather than one on the edge of expiry.

FunctionTool

Wrap a typed Python function as a :class:Tool.

The wrapped callable may optionally take a :class:RunContext as its first parameter (named ctx); if present it is injected and excluded from the model-facing schema. All other parameters are validated against a Pydantic model derived from the signature before the function runs.

Tool

Bases: Protocol

The pluggable tool interface.

schema

schema() -> dict[str, Any]

Return the OpenAI-style function-calling schema.

execute async

execute(ctx: RunContext, **kwargs: Any) -> Any

Run the tool with validated keyword arguments.

MCPTool

A single MCP tool exposed through the YAAB :class:Tool protocol.

OpenAPITool

A single OpenAPI operation exposed through the YAAB :class:Tool protocol.

Carries the resolved request recipe (method, path template, the names of path/query params, whether a JSON body is expected) plus the transport config (base URL, static headers, optional injected client). The model-facing input schema is the union of path params, query params, and the JSON requestBody's properties, so the model fills one flat argument object and the tool routes each value to its correct place in the request.

schema

schema() -> dict[str, Any]

Return the OpenAI function-calling schema (same shape as FunctionTool).

execute async

execute(ctx: RunContext, **kwargs: Any) -> Any

Issue the HTTP request, routing each kwarg to path/query/body.

Returns parsed JSON on success (falling back to text), or an error: string on transport failure or any non-2xx status — never raises, so a failed call surfaces to the model instead of crashing the run.

adapt_tool

adapt_tool(tool: Any) -> FunctionTool

Adapt a foreign tool, auto-detecting its ecosystem by its interface.

A tool exposing .invoke is treated as LangChain-style; one exposing only .run/._run as CrewAI-style. Anything that matches neither raises TypeError so a misuse fails loudly rather than silently.

from_crewai_tool

from_crewai_tool(tool: Any) -> FunctionTool

Wrap a CrewAI BaseTool (or anything with .name/.run).

CrewAI tools take keyword arguments, so the wrapper forwards **kwargs straight through to the foreign tool's run / _run method.

from_langchain_tool

from_langchain_tool(tool: Any) -> FunctionTool

Wrap a LangChain BaseTool (or anything with .name/.invoke).

The wrapped callable accepts arbitrary keyword arguments and forwards them to the foreign tool's invoke (preferred) / run / _run method, passing a single positional value when the tool takes one input and a dict otherwise.

as_headers

as_headers(credential: ToolCredential) -> dict[str, str]

Render a :class:ToolCredential into HTTP request headers.

  • api_key -> {header: value} (header name from the credential).
  • bearer / oauth2 -> {'Authorization': 'Bearer <token>'}.
  • basic -> {'Authorization': 'Basic <base64(value:token)>'}.

Raises :class:~yaab.exceptions.YaabError if a required field is missing, so a misconfigured credential fails loudly rather than sending a header with a literal None in it.

coerce_tools

coerce_tools(items: list[Any]) -> list[Tool]

Coerce a mixed list of callables/tools into :class:Tool instances.

A :class:~yaab.conditions.Step (a conditional tool, Step(tool, when=...)) passes through unchanged: it carries a guard the runner checks when building the model-facing schema, and its wrapped tool is unwrapped at call time. Everything else must be a tool or a plain callable.

tool

tool(fn: Callable[..., Any] | None = None, *, name: str | None = None, description: str | None = None, timeout: float | None = None, auth: ToolAuth | None = None) -> Any

Decorator turning a typed function into a :class:FunctionTool.

Usable bare (@tool) or parameterized (@tool(name=..., timeout=..., auth=...)). When auth is given, the framework resolves and injects a credential before each call — see :class:FunctionTool and :mod:.auth.

mcp_toolset

mcp_toolset(descriptors: list[dict[str, Any]], caller: CallFn) -> list[MCPTool]

Build :class:MCPTool objects from a server's tools/list response.

openapi_toolset

openapi_toolset(spec: dict[str, Any] | str, *, base_url: str | None = None, headers: dict[str, str] | None = None, client: Any | None = None, operations: list[str] | None = None) -> list[OpenAPITool]

Build one :class:OpenAPITool per operation in an OpenAPI 3.x document.

Parameters:

Name Type Description Default
spec dict[str, Any] | str

A parsed OpenAPI dict, a JSON string, or a YAML string. YAML is only attempted (via lazily-imported pyyaml) when the string isn't valid JSON, so JSON/dict callers never need pyyaml installed.

required
base_url str | None

Overrides the spec's servers[0].url. Useful for pointing a published spec at a staging host or a test transport.

None
headers dict[str, str] | None

Static headers attached to every request (e.g. an API key). The model can't see or alter these — they're caller-controlled auth.

None
client Any | None

An injected httpx.AsyncClient (e.g. one backed by httpx.MockTransport in tests). When omitted, each call creates and closes its own client.

None
operations list[str] | None

Optional allowlist of operationId\ s to include; anything not listed is skipped. The (slug) fallback name also matches.

None

Returns:

Type Description
list[OpenAPITool]

A list of tools, one per included operation.