Skip to content

Reference

Serving and integrations

Put a head behind HTTP, or in front of a tool-calling LLM.

The guides are Deploy and serve, Hot-swap into an agent and the production runbook. The endpoints of the service are listed in the runbook.

OpenAI-style tools

from tabagent.integrations.openai_tools import ToolFilter

tool_filter = ToolFilter("my_head", k=7)  # or the URL of a `tabagent serve` service
session = tool_filter.session(task={"instruction": goal})  # one per conversation
client.chat.completions.create(model=..., messages=messages, tools=session(messages, tools))

ToolFilter

ToolFilter(
    head,
    k: int = 9,
    always: Iterable[str] = (),
    defer_to_all: bool = True,
    adapter: OpenAIMessagesAdapter | None = None,
    trust_extractor: bool = False,
    *,
    task: dict[str, Any] | None = None,
    sandbox: Any = None,
    redact: Callable[[dict], dict] | str | None = None,
    allow_unpinned: bool = False,
)

Shortlist an agent's tools with a head before each LLM call (see the module docstring).

Parameters:

Name Type Description Default
head

a TabAgentHead, the directory it was saved to, hf://OWNER/REPO[@REVISION], or the URL of a tabagent serve service (http://host:8077; the service builds the prefix with its recorded adapter, and an unreachable service defers, so the full list is sent).

required
k int

tools to keep.

9
always Iterable[str]

tool names that are always kept.

()
defer_to_all bool

when the head defers the decision (its confidence gate, or an extractor failure), keep every tool.

True
adapter OpenAIMessagesAdapter | None

builds the live prefix from the messages; default the adapter recorded with the head, else OpenAIMessagesAdapter().

None
trust_extractor bool

when loading head from a directory, run its extractor in-process.

False
task dict[str, Any] | None

run-level task fields sent with every call ({"domain": "airline"}, say); __call__, select and session take further fields ({"instruction": ...}), which take precedence.

None
sandbox Any

when loading head from a directory or the Hub, see

None
redact Callable[[dict], dict] | str | None

when loading head from a directory or the Hub, see

None
allow_unpinned bool

when loading head from a directory or the Hub, see TabAgentHead.load (a served head is loaded, and checked, by tabagent serve).

last holds the head's answer for the latest select on this filter; a session keeps its own.

False

select

select(messages: list[dict], tools: list[dict], task: dict[str, Any] | None = None) -> list[str]

The names of the tools to send with messages: the head's top k and always, or every tool when the head defers.

session

session(
    task: dict[str, Any] | None = None, *, keep_used: bool = True, sticky: bool = True
) -> ToolSession

A new conversation (see ToolSession); task adds run-level fields for all its calls.

__call__

__call__(messages: list[dict], tools: list[dict], task: dict[str, Any] | None = None) -> list[dict]

The subset of tools to send with messages, in their original order.

ToolSession

ToolSession(
    tool_filter: ToolFilter,
    task: dict[str, Any] | None = None,
    *,
    keep_used: bool = True,
    sticky: bool = True,
)

The tool lists of one conversation, from a ToolFilter.

Each call sends the head's top k and the filter's always tools, plus

  • with keep_used, every tool the agent already called in the conversation;
  • with sticky, every tool shown at an earlier call, the earlier list first and the newly shown tools appended in catalog order, so the list only grows (a provider's prompt cache survives the calls that add nothing). Without sticky, the tools go in catalog order.

When the head defers, every tool is sent (with defer_to_all); with sticky they then stay. A session holds the state of its conversation only: start one per conversation. Its calls may come from several threads.

Attributes:

Name Type Description
shown list[str]

with sticky, the tools shown so far, in the order they are sent.

used list[str]

the tools the agent called so far.

last dict[str, Any] | None

the head's answer for the latest call, with the tools sent ("sent") and those kept only because the agent had used them ("kept_as_used").

select

select(messages: list[dict], tools: list[dict], task: dict[str, Any] | None = None) -> list[str]

The names of the tools to send with messages, in the order to send them.

HTTP service

RemoteHead

RemoteHead(url: str, timeout: float = 10.0)

A head served by tabagent serve, called over HTTP with the standard library (no extra needed).

decide takes the arguments of TabAgentHead.decide and returns the service's answer, so an agent whose environment cannot host the head (ToolFilter("http://..."), say) uses it like a local one. Send run= (the service builds the prefix with the head's recorded adapter) and JSON candidates (tool schemas, ids, {"id", "description", "args", "spec"} records, or Candidate objects, which are sent as such records, their catalog entries included). When the service cannot be reached, times out or fails (status 5xx), the decision is deferred with the reason in error, as when a local extractor fails, in the service's own shape for a decision it could not make (every candidate id in input order, empty scores); a request the service rejects (status 4xx) raises ValueError.

decide

decide(
    prefix: Optional[dict] = None,
    candidates: Optional[list] = None,
    k: Optional[int] = None,
    defer_below: Optional[float] = None,
    *,
    run: Optional[dict] = None,
) -> dict[str, Any]

The service's POST /decide answer (see TabAgentHead.decide).

create_app

create_app(
    head,
    *,
    request_timeout: Optional[float] = None,
    log_content: bool = False,
    drift: Any = True,
    drift_window: int = 500,
    threads: int = 8,
    max_batch: int = 256,
    warm: bool = True,
) -> Any

The FastAPI application serving head (a TabAgentHead).

request_timeout: seconds the extractor gets per decision, a positive number (see the module docstring; None: no deadline beyond the extractor sandbox's own). log_content: also log each request's prefix, run, candidates, answer and error message (off by default: they are the agent's data). drift: monitor feature drift against the head's training statistics (True), not at all (False), or with a given tabagent.drift.DriftMonitor; drift_window decisions are compared. threads: decisions computed at once. max_batch: requests per /decide_batch call. warm: start the warm extractor workers when the application starts (/ready answers 503 until enough of them run); with False they start at the first decisions, and the service is ready at once.

CUGA

CugaShortlister

CugaShortlister(
    head: Any,
    k: int = 9,
    defer_below: float | None = None,
    trust_extractor: bool = False,
    sandbox: Any = None,
    redact: Any = None,
    allow_unpinned: bool = False,
)

Bases: _Swap

CUGA's API shortlister as a head: the top k of the current app's APIs, as CUGA's APIDetails.

Parameters:

Name Type Description Default
head Any

a TabAgentHead onboarded on ShortlisterAgent, its directory, hf://OWNER/REPO, or the URL of a tabagent serve service.

required
k int

APIs to return (CUGA's shortlister usually returns 3 to 9).

9
defer_below float | None

the confidence gate (default: the head's calibrated threshold, if any).

None
trust_extractor bool

when loading head from a directory, see

False
sandbox Any

when loading head from a directory, see

None
redact Any

when loading head from a directory, see

None
allow_unpinned bool

when loading head from a directory, see TabAgentHead.load.

False

shortlist

shortlist(run: dict[str, Any], apis: Any) -> list[dict[str, Any]] | None

[{"name", "relevance_score", "reasoning"}] for CUGA's ShortListerOutput.result, best first; None when the head defers (keep CUGA's LLM call).

CugaAppMatcher

CugaAppMatcher(
    head: Any,
    defer_below: float | None = None,
    trust_extractor: bool = False,
    sandbox: Any = None,
    redact: Any = None,
    allow_unpinned: bool = False,
)

Bases: _Swap

CUGA's app matcher as a multi-label head: the apps a task needs, among those CUGA offers.

Parameters:

Name Type Description Default
head Any

a TabAgentHead onboarded on TaskAnalyzerAgent (kind="multilabel"), its directory, hf://OWNER/REPO, or the URL of a tabagent serve service.

required
defer_below float | None

the confidence gate (default: the head's calibrated threshold, if any).

None
trust_extractor bool

when loading head from a directory.

False
sandbox Any

when loading head from a directory.

None
redact Any

when loading head from a directory.

None
allow_unpinned bool

when loading head from a directory.

False

match

match(run: dict[str, Any], apps: list[Any]) -> list[str] | None

The names of the apps the task needs (the head's multi-label decision, at least one); None when the head defers (keep CUGA's LLM call).

run_so_far

run_so_far(tracker: Any) -> dict[str, Any]

The run so far as CUGA's ActivityTracker holds it, in the shape of its trajectory files: the intent, the dataset_name and the steps recorded up to now (pydantic Step objects or dicts).