Agents and integrations¶
AgentWithConstraints checks every tool call before
it runs, with a smolagents or native (OpenAI-compatible) backend. The lower-level integrations plug the same
checks into an agent you build yourself.
Agent wrappers¶
Backend-agnostic agent wrappers.
These classes dispatch to the smolagents or the native (OpenAI-compatible) backend
depending on the backend= parameter, while exposing a single, consistent public API.
Classes¶
Agent– base agent (smolagents backend only)AgentWithAdditionalTools– MCP-enabled agent (smolagents backend only)AgentWithSubAgents– sub-agent orchestrator (smolagents backend only)AgentWithConstraints– FOLTL constraint enforcement (smolagents or native)MultiTurnAgent– one conversation over several user turns (native)
All run() methods return {"answer", "metrics", "error"}.
See docs/reference.md for the full return-value schema.
Agent
¶
Agent(tools: Optional[List[Any]] = None, model: Optional[str] = None, api_key: Optional[str] = None, provider: Optional[str] = None, max_steps: int = 10, model_seed: Optional[int] = None, model_instance: Optional[Any] = None, base_url: Optional[str] = None, backend: str = 'smolagents', nudge_max: int = 1, max_termination_nudges: int = 0, max_blocked_steps: Optional[int] = None, enforcer_kwargs: Optional[Dict[str, Any]] = None)
Backend-agnostic base agent.
Delegates to the smolagents backend (default) or the hand-coded
native backend (OpenAI-compatible chat-completions, incl. the HF router).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tools
|
Optional[List[Any]]
|
Tool instances. |
None
|
model
|
Optional[str]
|
Model name / ID. |
None
|
api_key
|
Optional[str]
|
API key. |
None
|
provider
|
Optional[str]
|
HF Inference provider name (native: encoded as a
|
None
|
max_steps
|
int
|
Maximum agent steps. |
10
|
model_seed
|
Optional[int]
|
Optional seed for reproducible sampling. |
None
|
model_instance
|
Optional[Any]
|
Pre-constructed model object (native: an |
None
|
base_url
|
Optional[str]
|
OpenAI-compatible base URL (native backend only). |
None
|
backend
|
str
|
|
'smolagents'
|
AgentWithAdditionalTools
¶
AgentWithAdditionalTools(tools: Optional[List[Any]] = None, mcp_servers: Optional[Dict[str, Any]] = None, model: Optional[str] = None, api_key: Optional[str] = None, provider: Optional[str] = None, max_steps: int = 10, model_seed: Optional[int] = None, model_instance: Optional[Any] = None, backend: str = 'smolagents')
Backend-agnostic MCP-enabled agent.
Currently delegates to the smolagents backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tools
|
Optional[List[Any]]
|
Local tool instances appended after MCP tools. |
None
|
mcp_servers
|
Optional[Dict[str, Any]]
|
|
None
|
model
|
Optional[str]
|
Model name / ID. |
None
|
api_key
|
Optional[str]
|
API key. |
None
|
provider
|
Optional[str]
|
HF Inference provider name. |
None
|
max_steps
|
int
|
Maximum agent steps. |
10
|
model_seed
|
Optional[int]
|
Optional seed for reproducible sampling. |
None
|
model_instance
|
Optional[Any]
|
Pre-constructed model object. |
None
|
backend
|
str
|
Backend to use. Only |
'smolagents'
|
AgentWithSubAgents
¶
AgentWithSubAgents(tools: Optional[List[Any]] = None, mcp_servers: Optional[Dict[str, Any]] = None, model: Optional[str] = None, api_key: Optional[str] = None, provider: Optional[str] = None, max_steps: int = 10, sub_agent_max_steps: int = 15, model_seed: Optional[int] = None, model_instance: Optional[Any] = None, backend: str = 'smolagents')
Backend-agnostic sub-agent orchestrator.
Currently delegates to the smolagents backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tools
|
Optional[List[Any]]
|
Local tools forwarded to every sub-agent. |
None
|
mcp_servers
|
Optional[Dict[str, Any]]
|
MCP server config forwarded to every sub-agent. |
None
|
model
|
Optional[str]
|
Model name / ID. |
None
|
api_key
|
Optional[str]
|
API key. |
None
|
provider
|
Optional[str]
|
HF Inference provider name. |
None
|
max_steps
|
int
|
Coordinator max steps. |
10
|
sub_agent_max_steps
|
int
|
Max steps for each spawned sub-agent. |
15
|
model_seed
|
Optional[int]
|
Optional seed. |
None
|
model_instance
|
Optional[Any]
|
Pre-constructed model shared by all agents. |
None
|
backend
|
str
|
Backend to use. Only |
'smolagents'
|
EnforcementConfig
dataclass
¶
EnforcementConfig(constraints: Optional[List[Any]] = None, constraint_severities: Optional[Dict[str, ConstraintSeverity]] = None, default_severity: ConstraintSeverity = HARD_STOP, max_soft_attempts: int = 3, soft_block_mode: str = 'cumulative', max_consecutive_soft_attempts: Optional[int] = None, nudge_max: int = 1, max_termination_nudges: int = 0, enforcer_kwargs: Optional[Dict[str, Any]] = None)
The enforcement settings of an agent, in one place.
AgentWithConstraints(..., enforcement=EnforcementConfig(...)) and
MultiTurnAgent(..., enforcement=...) take it instead of the same settings as
separate keywords (which still work; this wins where both are given). See
agentltl.Enforcer for what each one does.
AgentWithConstraints
¶
AgentWithConstraints(tools: Optional[List[Any]] = None, mcp_servers: Optional[Dict[str, Any]] = None, constraints: Optional[List[Any]] = None, constraint_severities: Optional[Dict[str, ConstraintSeverity]] = None, default_severity: ConstraintSeverity = HARD_STOP, max_soft_attempts: int = 3, soft_block_mode: str = 'cumulative', max_consecutive_soft_attempts: Optional[int] = None, model: Optional[Any] = None, api_key: Optional[str] = None, provider: Optional[str] = None, model_seed: Optional[int] = None, model_instance: Optional[Any] = None, max_steps: int = 10, system_prompt: Optional[str] = None, strict_runtime_safety: bool = False, base_url: Optional[str] = None, backend: str = 'smolagents', nudge_max: int = 1, max_termination_nudges: int = 0, max_blocked_steps: Optional[int] = None, enforcer_kwargs: Optional[Dict[str, Any]] = None, enforcement: Optional[EnforcementConfig] = None)
Backend-agnostic FOLTL constrained agent.
Dispatches to the smolagents or native backend depending on backend=. The public
interface is identical regardless of backend; both drive an agentltl.Enforcer.
Parameters shared by all backends¶
tools, constraints, constraint_severities, default_severity,
max_soft_attempts, soft_block_mode, max_consecutive_soft_attempts,
max_steps, nudge_max, max_termination_nudges, enforcer_kwargs (further
agentltl.Enforcer settings)
Model / connectivity parameters¶
model – string model name; resolved per-backend api_key – API key (smolagents: HF token; native: OpenAI-compatible key) provider – HF Inference provider name model_seed – optional reproducible-sampling seed model_instance – pre-built model object passed through to the backend mcp_servers – MCP server config dict (smolagents only) system_prompt – optional system prompt (native backend) base_url – OpenAI-compatible endpoint (native backend) max_blocked_steps – turns in which nothing ran, allowed beyond max_steps (native)
Backend selection¶
backend : str, default "smolagents"
"smolagents" – use SmolAgentsAgentWithConstraints
"native" – use NativeOpenAIAgent
Returns¶
run() returns {"answer", "metrics", "error"} with constraint
fields merged into metrics. See docs/reference.md.
MultiTurnAgent
¶
MultiTurnAgent(tools: Optional[List[Any]] = None, model: Optional[Any] = None, api_key: Optional[str] = None, provider: Optional[str] = None, base_url: Optional[str] = None, max_steps: int = 10, max_blocked_steps: Optional[int] = None, max_termination_nudges: int = 0, model_seed: Optional[int] = None, model_instance: Optional[Any] = None, system_prompt: Optional[str] = None, constraints: Optional[List[Any]] = None, constraint_severities: Optional[Dict[str, ConstraintSeverity]] = None, default_severity: ConstraintSeverity = HARD_STOP, max_soft_attempts: int = 3, soft_block_mode: str = 'cumulative', max_consecutive_soft_attempts: Optional[int] = None, nudge_max: int = 1, strict_runtime_safety: bool = False, backend: str = 'native', enforcer_kwargs: Optional[Dict[str, Any]] = None, agent_cls: Optional[Any] = None, agent_kwargs: Optional[Dict[str, Any]] = None, enforcement: Optional[EnforcementConfig] = None)
A multi-turn agent built on the hand-coded NativeOpenAIAgent.
Unlike calling Agent.run() once per turn (which resets the conversation
each call), this keeps ONE persistent conversation across turns, so the model
SEES prior turns (continuity). It emits a single continuous trace (monotonic
step numbers, each tool call tagged with its turn) and — when
constraints are supplied — enforces them at runtime across the whole
session (e.g. an ordering constraint spanning two turns).
Native backend only (the conversation-persistence primitives live there).
Example:
mt = MultiTurnAgent(tools=[...], model="Qwen/...", provider="novita",
base_url="https://router.huggingface.co/v1")
result = mt.run(["turn 1 text", "turn 2 text", ...])
result["answers"] # final answer per turn
result["per_turn"] # [{answer, metrics, error}, ...] (per-turn trace)
result["metrics"] # aggregate continuous trace for verify_trace
run_turn
¶
Run one user turn against the persistent conversation. Returns
{"answer", "metrics", "error"} for that turn.
run
¶
Run a list of user turns sequentially in one persistent session.
Returns {"answers", "per_turn", "metrics", "error"} where metrics
is the aggregate continuous trace (suitable for verify_trace) and
per_turn holds each turn's individual result.
smolagents¶
agentltl.integrations.smolagents.constrained_agent.ToolCallingAgentWithConstraints
¶
ToolCallingAgentWithConstraints(tools, model, *, constraints: list | None = None, constraint_severities: Dict[str, ConstraintSeverity] | None = None, default_severity: ConstraintSeverity = HARD_STOP, max_soft_attempts: int = 3, soft_block_mode: 'str | SoftBlockMode' = 'cumulative', max_consecutive_soft_attempts: 'int | None' = None, nudge_max: int = 1, max_termination_nudges: int = 0, enforcer_kwargs: Optional[Dict[str, Any]] = None, prompt_templates=None, planning_interval: int | None = None, stream_outputs: bool = False, max_tool_threads: int | None = None, strict_runtime_safety: bool = False, _skip_runtime_safety_check: bool = False, **kwargs)
Bases: ToolCallingAgent
A ToolCallingAgent whose tool calls are judged by an
agentltl.Enforcer before they run.
Parameters¶
tools, model, prompt_templates, planning_interval, stream_outputs,
max_tool_threads, **kwargs
Forwarded to ToolCallingAgent.
constraints, constraint_severities, default_severity, max_soft_attempts,
soft_block_mode, max_consecutive_soft_attempts, nudge_max, max_termination_nudges
Forwarded to agentltl.Enforcer. Constraints and severities can also be
given per run (run).
enforcer_kwargs
Further agentltl.Enforcer settings (rank, render, ...).
run
¶
run(task: str, *, constraints: list | None = None, constraint_severities: Dict[str, ConstraintSeverity] | None = None, stream: bool = False, reset: bool = True, images=None, additional_args: dict | None = None, max_steps: int | None = None, return_full_result: bool | None = None)
Run the agent with pre-execution constraint checking.
process_tool_calls
¶
process_tool_calls(chat_message: ChatMessage, memory_step: ActionStep) -> Generator[ToolCall | ToolOutput, None, None]
Judge each tool call of this model message before it runs, one by one so later calls see the earlier ones in the trace.
get_constraint_status
¶
The enforcer's status (see agentltl.Enforcer.get_constraint_status),
plus blocked_tool_call: the call a stop refused, if any.