Skip to content

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 model:provider suffix when talking to the HF router).

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 openai.OpenAI client).

None
base_url Optional[str]

OpenAI-compatible base URL (native backend only).

None
backend str

"smolagents" (default) or "native".

'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]]

{name: server_config_dict} mapping.

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" is supported.

'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" is supported.

'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

agent property

agent: Any

The underlying agent (an agent_cls instance).

reset

reset() -> None

Start a fresh session (clears conversation, enforcer, and trace).

run_turn

run_turn(task: str) -> Dict[str, Any]

Run one user turn against the persistent conversation. Returns {"answer", "metrics", "error"} for that turn.

run

run(turns: List[str]) -> Dict[str, Any]

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

get_constraint_status() -> Dict[str, Any]

The enforcer's status (see agentltl.Enforcer.get_constraint_status), plus blocked_tool_call: the call a stop refused, if any.