Reference
Onboarding and heads¶
Turn agent logs into a head, and load a saved one.
onboard is the one-call path from agent logs to a deployable head. load reads a saved head back, from a local
directory or from the Hugging Face Hub. A TabAgentHead is the fitted model plus the TabSchema extractor that
feeds it: the drop-in replacement for one agent decision.
import tabagent
head = tabagent.onboard("./agent_logs", decision="ToolShortlist")
print(head.report) # grouped cross-validation vs BM25 and chance, latency, cost per decision
head.save("my_head")
head.decide(prefix, candidates, k=5) # {"candidates", "scores", "confidence", "deferred", "error"}
head = tabagent.load("my_head", trust_extractor=True) # trust only an extractor you have reviewed
onboard
¶
onboard(
logs: str | Path | list[Trajectory],
decision: str | None = None,
*,
adapter: Any = "auto",
llm: LLM | None = None,
model: str | None = None,
kind: str | None = None,
out: str | Path | None = None,
n_analyze: int | None = None,
max_cost_usd: float | None = None,
prices: dict[str, tuple[float, float]] | None = None,
dry_run: bool = False,
redact: Callable[[dict], dict] | None = None,
search: str = "fast",
n_splits: int = 5,
llm_cost_per_call: float | None = None,
trust_extractor: bool = False,
run_dir: str | Path | None = None,
config: TabSchemaConfig | None = None,
gate_coverage: float | None = None,
iterations: int | None = None,
sandbox: Any = None,
stage_models: dict[str, str] | None = None,
fallback_model: str | None = None,
lazy: bool | None = None,
on_other_formats: str = "skip",
) -> TabAgentHead | DryRun
Onboard an agent decision component from its logs (see the module docstring).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
logs
|
str | Path | list[Trajectory]
|
a file or directory of agent logs, or a list of |
required |
decision
|
str | None
|
the component to replace (see |
None
|
adapter
|
Any
|
the log adapter, or |
'auto'
|
llm
|
LLM | None
|
the TabSchema LLM, or the model name to build one from environment keys (default GPT-5.4). |
None
|
model
|
str | None
|
the TabSchema LLM, or the model name to build one from environment keys (default GPT-5.4). |
None
|
kind
|
str | None
|
the decision pattern: |
None
|
out
|
str | Path | None
|
save the head to this directory. |
None
|
n_analyze
|
int | None
|
decision points analyzed by the LLM (default 20). |
None
|
max_cost_usd
|
float | None
|
stop TabSchema when its LLM cost exceeds this. Needs a known price for the model
( |
None
|
prices
|
dict[str, tuple[float, float]] | None
|
|
None
|
dry_run
|
bool
|
return a |
False
|
redact
|
Callable[[dict], dict] | None
|
applied to every raw trajectory before anything can reach the LLM provider (it gets a copy; a
run read lazily stays lazy and is redacted each time it is read, so |
None
|
search
|
str
|
|
'fast'
|
n_splits
|
int
|
folds of the grouped cross-validation in the report. |
5
|
llm_cost_per_call
|
float | None
|
the replaced LLM call's cost, to report the savings. |
None
|
trust_extractor
|
bool
|
run the LLM-written extractor in-process. Off by default: the extractor then runs in the sandbox, since trajectories are untrusted text that reaches the LLM writing the code. |
False
|
sandbox
|
Any
|
where the LLM-written code runs, in discovery, in the decision table and in the returned head:
|
None
|
run_dir
|
str | Path | None
|
the TabSchema run directory itself (default: a new one under |
None
|
stage_models
|
dict[str, str] | None
|
a model per TabSchema stage, e.g. |
None
|
fallback_model
|
str | None
|
asked once, for any stage, when the provider's content filter stops an answer. |
None
|
lazy
|
bool | None
|
read the runs again from their files when they are needed instead of holding them all (default:
from 256 MB of logs); |
None
|
on_other_formats
|
str
|
with |
'skip'
|
config
|
TabSchemaConfig | None
|
a full |
None
|
gate_coverage
|
float | None
|
calibrate the confidence gate so this share of decisions stays with the head (rankings). |
None
|
iterations
|
int | None
|
override the CatBoost iteration count (for quick runs). |
None
|
Returns:
| Type | Description |
|---|---|
TabAgentHead | DryRun
|
The fitted Before any LLM call (and in a dry run) the data is checked: some trajectories must be successful, the
decision must occur at least twice in at least 2 task groups, and the adapter must give its labels and
candidates; otherwise |
load
¶
load(
path: str | Path, trust_extractor: bool = False, trust_code: bool = False, **head_options: Any
) -> TabAgentHead | TabAgent
Load a saved head: a TabAgentHead for a directory written by onboard (it has head.json),
else the TabAgent artifact written by TabAgent.save.
path is a local directory or a Hugging Face Hub repository, hf://OWNER/REPO[@REVISION], which is
downloaded first (pip install "tabagent[hub]"; see tabagent.hub) and then loaded and verified
exactly as a local directory.
A TabAgentHead decides from a trajectory prefix (decide(prefix, candidates, k=...)); a bare
TabAgent decides from candidate rows (decide(rows, k=...)). trust_extractor, trust_code
and the head_options (sandbox, redact, adapter) are described in
TabAgentHead.load; a TabAgent has no extractor and takes no head_options.
TabAgentHead
dataclass
¶
TabAgentHead(
agent: TabAgent,
target: str,
extractor_code: str | None = None,
report: Any = None,
discovery: DiscoveryReport | None = None,
gate_threshold: float | None = None,
trust_extractor: bool = False,
adapter: Any = None,
sandbox: Any = None,
redact: Callable[[dict], dict] | str | None = None,
extractor_tests: dict | None = None,
allow_unchecked_extractor: bool = False,
relative_features: bool | None = None,
)
A fitted TabAgent with the TabSchema extractor that feeds it: the drop-in replacement for one
agent decision.
decide(prefix, candidates) runs the extractor on the trajectory prefix, builds one row per candidate
and returns the head's decision; decide(run=..., candidates=...) first builds the prefix from the live
run with the adapter the head was trained with (live_prefix). An extractor with a per-candidate
function (extract_candidate_features) runs once per decision, on the prefix and on every candidate,
in one sandbox call, exactly as for the training rows. Heads come from onboard and are persisted
with save and load.
Attributes:
| Name | Type | Description |
|---|---|---|
agent |
TabAgent
|
the fitted |
target |
str
|
the replaced decision component (for example |
extractor_code |
str | None
|
the compiled TabSchema extractor ( |
report |
Any
|
the onboarding evaluation report ( |
discovery |
DiscoveryReport | None
|
the TabSchema discovery report. |
gate_threshold |
float | None
|
decisions with a lower confidence are marked |
trust_extractor |
bool
|
run the extractor in-process (fast; for reviewed code) instead of in the sandbox. |
adapter |
Any
|
the log adapter of the training trajectories (an adapter or its |
sandbox |
Any
|
where an untrusted extractor runs: |
redact |
Callable[[dict], dict] | str | None
|
the function applied to each training trajectory before discovery, as a callable or a
|
extractor_tests |
dict | None
|
the extractor's golden tests ( |
allow_unchecked_extractor |
bool
|
run, still in the sandbox, an extractor that fails those static checks (a
head saved before they were re-applied at serve time, whose |
relative_features |
bool | None
|
whether the recipe search kept the within-decision relative features
( |
decide
¶
decide(
prefix: dict[str, Any] | None = None,
candidates=None,
k: int | None = None,
defer_below: float | None = None,
*,
run: dict[str, Any] | None = None,
trace: dict[str, Any] | None = None,
) -> dict[str, Any]
Score one live decision.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prefix
|
dict[str, Any] | None
|
the trajectory before the decision, normalized by the adapter the head was onboarded with
(what the adapter's |
None
|
candidates
|
the legal candidates: ids, |
None
|
|
k
|
int | None
|
return the top |
None
|
defer_below
|
float | None
|
confidence threshold of the gate; defaults to the calibrated |
None
|
run
|
dict[str, Any] | None
|
instead of |
None
|
trace
|
dict[str, Any] | None
|
a dict that receives the decision's timings in seconds ( |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
|
live_prefix
¶
The prefix of a live decision, built from run (the run so far, in the format of the training
logs, with its run-level task fields) exactly as the training prefixes were: redact first, then
the head's adapter (or adapter; see tabagent.adapters.live_prefix).
warm
¶
Start the extractor's warm workers now rather than at the first decision (a serving process calls
this at start-up). Returns the number of running workers (0 without a warm pool). Raises
ExtractorBrokenError when the extractor cannot run at all (it does not compile, or breaks the
extraction rules).
close
¶
Stop the extractor's warm workers, if any. A later decision starts a new pool.
calibrate_gate
¶
Set gate_threshold so that target_coverage of the cross-validated decisions stay with the
head and the least confident 1 - target_coverage are deferred to the LLM (App. N.3). Returns the
threshold. Rankings only: a cross-validated single-class head keeps no scores to calibrate on.
save
¶
Write the head to the directory path: the model artifact (model/), extract.py and its
golden tests (extractor_tests.json, trajectory snippets), head.json (with the adapter and its
prefix settings, the redaction function's import path, when known, and the paper's citation) and,
when present, the evaluation and discovery reports. A card that pins no hash for the extractor gets
the hash of extract.py before it is written, so load can check the code.
load
classmethod
¶
load(
path: str | Path,
trust_extractor: bool = False,
trust_code: bool = False,
*,
sandbox: Any = None,
redact: Callable[[dict], dict] | str | None = None,
adapter: Any = None,
allow_unpinned: bool = False,
allow_unchecked_extractor: bool = False,
) -> TabAgentHead
Load a saved head from a directory or hf://OWNER/REPO[@REVISION] (tabagent.hub).
extract.py must match the hash recorded in the card. A card that records no hash (a head saved
before the hash was always pinned) is refused, since its code could not be checked; after reviewing
extract.py, allow_unpinned=True loads it with a warning, and saving the head again pins it.
trust_extractor=True runs the extractor in-process (fast); only do this for an extractor you have
reviewed. Otherwise it runs in sandbox (see the class attributes). trust_code allows card
features computed by modules outside tabagent. adapter overrides the adapter recorded in
head.json. redact is never imported from head.json: when the head records one and none is
passed, a warning says so, since live runs then reach the extractor unredacted.
allow_unchecked_extractor is described in the class attributes.
features_for
¶
The extractor's features for one trajectory prefix: every extractor column of the card, None where the extractor gave no value or failed (as in training).
candidate_features_for
¶
The per-candidate features of a decision: for each candidate (as decide takes them), every
per-candidate column of the card, None where the extractor gave no value or failed (as in
training).
DryRun
dataclass
¶
DryRun(
n_trajectories: int,
n_successful: int,
n_decision_points: int,
n_analyzed: int,
est_input_tokens: int,
est_output_tokens: int,
est_cost_usd: float | None,
components: dict[str, int] = dict(),
model: str = DEFAULT_MODEL,
problems: list[str] = list(),
stages: dict[str, dict[str, Any]] = dict(),
warnings: list[str] = list(),
)
What discovery would process, an estimate of its size and cost per stage (stages;
tabagent.tabschema.estimate), and the problems that would stop a real run before any LLM call
(problems).
RequestError
¶
Bases: ValueError
A decision request the head cannot answer as given (the HTTP service answers it with status 400): both a prefix and a run, a run the head cannot turn into a prefix, a ranking head without candidates, a malformed candidate. A failure of the head itself is not one.