Skip to content

Agent

The Agent is the orchestrator that combines connectors, an LLM, and the domain model into a working maintenance assistant. It receives messages from channels (CLI, Telegram, Slack, …), resolves referenced assets, gathers context from connectors, calls the LLM with domain-aware prompts, and executes tool calls.

This page is the auto-generated API reference. For tutorial-level usage see Quickstart and Architecture.

Agent

The central runtime class. Public attributes worth knowing:

  • sandbox — boolean property with a propagating setter. When mutated after construction (e.g. agent.sandbox = False to switch from sandbox to live), the change propagates to the internal workflow engine so write actions are no longer intercepted.
  • tracer — the ActionTracer instance recording every action.
  • plant — the Plant registered to this agent.

Agent

Agent(*, name: str = 'Machina Agent', description: str = 'Maintenance AI assistant', plant: Plant | None = None, connectors: list[Any] | None = None, channels: list[Any] | None = None, llm: str | LLMProvider = 'openai:gpt-4o', temperature: float = 0.1, max_history: int = 20, workflows: list[Workflow] | None = None, sandbox: bool = False, confirmations: bool = True)

Maintenance AI agent that orchestrates reasoning and actions.

The agent receives user queries, resolves referenced assets, gathers context from configured connectors, and uses an LLM to produce grounded, domain-aware responses.

Parameters:

Name Type Description Default
name str

Human-readable agent name.

'Machina Agent'
description str

What this agent specialises in.

'Maintenance AI assistant'
plant Plant | None

The plant with its asset registry.

None
connectors list[Any] | None

List of connector instances to register.

None
channels list[Any] | None

Communication channels (Telegram, CLI, etc.).

None
llm str | LLMProvider

LLM provider string (e.g. "openai:gpt-4o") or an :class:LLMProvider instance.

'openai:gpt-4o'
temperature float

LLM sampling temperature.

0.1
max_history int

Maximum conversation turns to keep in memory.

20
workflows list[Workflow] | None

List of workflow definitions to register.

None
sandbox bool

If True, write actions are logged but not executed.

False
confirmations bool

If True (default), the agent requires human confirmation before executing write/mutation tool calls.

True
Example
from machina import Agent, Plant
from machina.connectors.cmms import GenericCmmsConnector
from machina.connectors.comms.cli import CliChannel

plant = Plant(name="Demo Plant")
cmms = GenericCmmsConnector(data_dir="sample_data/cmms")

agent = Agent(
    name="Maintenance Assistant",
    plant=plant,
    connectors=[cmms],
    channels=[CliChannel()],
    llm="openai:gpt-4o",
)
agent.run()

sandbox property writable

sandbox: bool

Whether write actions are intercepted (True) or executed.

Read this attribute through normal access — no behaviour change for existing call sites that branch on if self.sandbox.

confirmations property writable

confirmations: bool

Whether write/mutation tool calls require human confirmation.

Read this attribute through normal access — the value is consumed inside the agent loop to gate side-effecting tool calls. Unlike :attr:sandbox, there is no contextvar or engine snapshot: the switch is purely agent-loop-local.

workflows property

workflows: dict[str, Workflow]

Registered workflows (read-only copy).

from_config classmethod

from_config(path: str | Path) -> Agent

Create an Agent from a machina.yaml configuration file.

Connectors and channels are instantiated from their type strings. Workflows cannot be defined in YAML (they may contain Python callables); register them after construction with :meth:register_workflow.

Parameters:

Name Type Description Default
path str | Path

Path to the YAML configuration file.

required

Returns:

Type Description
Agent

A fully configured Agent instance.

Example
from machina import Agent

agent = Agent.from_config("machina.yaml")
agent.run()

register_workflow

register_workflow(workflow: Workflow) -> None

Register a workflow for later execution.

Parameters:

Name Type Description Default
workflow Workflow

The workflow definition to register.

required

trigger_workflow async

trigger_workflow(workflow_name: str, event: dict[str, Any] | None = None) -> WorkflowResult

Trigger a registered workflow by name.

Parameters:

Name Type Description Default
workflow_name str

Name of a previously registered workflow.

required
event dict[str, Any] | None

Event data to pass to the workflow.

None

Returns:

Name Type Description
A WorkflowResult

class:WorkflowResult with per-step outcomes.

Raises:

Type Description
WorkflowError

If the workflow is not found.

start async

start() -> None

Connect all connectors and load assets.

stop async

stop() -> None

Disconnect all connectors and channels.

handle_message async

handle_message(text: str, *, chat_id: str = 'default', confirmer: Callable[[str], Awaitable[bool]] | None = None, user_id: str = '') -> str

Process a user message and return the agent's response text.

This is the main entry point for programmatic usage. The returned string is the rendered answer with inline [n] citation markers renormalized to 1..N by first appearance and the trailing <citations> block stripped. Use :meth:handle_message_full to also access structured :class:Citation objects — citations[n-1] aligns with the inline [n] marker.

Parameters:

Name Type Description Default
text str

The user's message.

required
chat_id str

Identifier for the conversation.

'default'
confirmer Callable[[str], Awaitable[bool]] | None

Optional async callable that renders a confirmation prompt and returns the user's yes/no decision. Supplied by a channel that can confirm a write synchronously (e.g. CliChannel). When None and :attr:confirmations is on, a mutating tool call is NOT executed (fail-safe).

None
user_id str

Identifier for the sender, forwarded for cross-user confirmation scoping. Note: confirmations only gates writes that flow through the agent LLM loop; trigger_workflow is a deliberate direct-execution path guarded by sandbox only.

''

Returns:

Type Description
str

The agent's response text.

Raises:

Type Description
LLMError

If the underlying LLM call fails.

handle_message_full async

handle_message_full(text: str, *, chat_id: str = 'default', confirmer: Callable[[str], Awaitable[bool]] | None = None, user_id: str = '') -> AgentResponse

Process a user message and return the structured agent response.

Parameters:

Name Type Description Default
text str

The user's message.

required
chat_id str

Identifier for the conversation.

'default'
confirmer Callable[[str], Awaitable[bool]] | None

Optional async callable that renders a confirmation prompt and returns the user's yes/no decision (see :meth:handle_message). When None and :attr:confirmations is on, a mutating tool call is NOT executed (fail-safe — a programmatic caller that wants autonomous writes sets confirmations=False or passes a confirmer).

None
user_id str

Identifier for the sender, forwarded for cross-user confirmation scoping.

''

Returns:

Name Type Description
An AgentResponse

class:AgentResponse with the rendered text and any

AgentResponse

citations the agent emitted.

Raises:

Type Description
LLMError

If the underlying LLM call fails.

run

run() -> None

Start the agent with all channels (blocking, sync wrapper).

Connects connectors, loads assets, and starts listening on all configured channels. Automatically detects Jupyter notebooks and other environments with an already-running event loop.

EntityResolver

Resolves free-text mentions in user messages (e.g. "the pump P-201", "compressore C-301") to concrete assets registered on the agent's Plant.

Both examples above resolve on the asset ID (P-201, C-301), which is language-independent — the surrounding word does the work only when it matches the asset's registered name. There is no cross-language matching and no typo tolerance: matching is verbatim containment at every stage. To make an asset resolvable by a word other than its registered name — the local-language term, plant jargon, a nickname — put that word in Asset.aliases, which is searched at the same authority as the name.

When several candidates tie at the top, resolution is ambiguous: the runtime withholds the asset for that turn, asks which one is meant, and remembers the candidates so the next message can answer by ID, by name, or by position.

EntityResolver

EntityResolver(plant: Plant)

Resolves natural language references to assets in a plant.

Uses a cascading strategy: 1. Exact ID match (e.g. "P-201") 2. Name match (e.g. "cooling water pump"), including any curated Asset.aliases — the plant's own words for the machine, searched at the same authority as the registered name 3. Location match (e.g. "building A") 4. Keyword match — verbatim token containment across all asset fields (no typo tolerance)

Parameters:

Name Type Description Default
plant Plant

The plant containing the asset registry.

required
Example
resolver = EntityResolver(plant)
matches = resolver.resolve("the pump in building A")
if matches:
    asset = matches[0].asset

resolve

resolve(text: str) -> list[ResolvedEntity]

Resolve a natural language reference to zero or more assets.

Parameters:

Name Type Description Default
text str

User input that may reference an asset.

required

Returns:

Type Description
list[ResolvedEntity]

List of :class:ResolvedEntity results, ordered by confidence

list[ResolvedEntity]

(highest first). Empty if no matches found.

ResolvedEntity dataclass

ResolvedEntity(asset: Asset, confidence: float, match_reason: str = '')

Result of entity resolution.

confidence is required. It previously defaulted to 1.0, which made an entity built without a stated confidence maximally confident — the authority gate then acted on a match nobody had scored. Omitting it is now a TypeError at construction rather than silent full trust.

Parameters:

Name Type Description Default
asset Asset

The matched asset.

required
confidence float

Confidence score (0.0-1.0).

required
match_reason str

How the match was determined.

''

LLMProvider

Thin wrapper around LiteLLM exposing complete() and complete_with_tools(). Constructed implicitly by Agent(llm="provider:model") but can also be passed in explicitly for custom providers.

LLMProvider

LLMProvider(model: str = 'openai:gpt-4o', *, temperature: float = 0.1, max_tokens: int = 4096, request_timeout: float = 120.0, tracer: ActionTracer | None = None)

Provider-agnostic LLM interface.

Wraps LiteLLM to provide async complete() and complete_with_tools() methods. Machina's agent layer uses this instead of calling LLM libraries directly.

Both methods pass drop_params=True to LiteLLM so that parameters a given model does not accept are silently dropped rather than raising. The motivating case is OpenAI reasoning models (o1/o3/gpt-5 family) that reject any explicit temperature other than the default 1 with a 400 error; LiteLLM knows the per-model support matrix and omits the unsupported value instead of failing the call.

Parameters:

Name Type Description Default
model str

Provider and model identifier (e.g. "openai:gpt-4o").

'openai:gpt-4o'
temperature float

Sampling temperature.

0.1
max_tokens int

Maximum tokens in the response.

4096
tracer ActionTracer | None

Optional ActionTracer for cost/token instrumentation.

None

complete async

complete(messages: list[dict[str, str]], *, conversation_id: str = '', **kwargs: Any) -> str

Send a chat completion request and return the response text.

Parameters:

Name Type Description Default
messages list[dict[str, str]]

Chat messages in OpenAI format.

required
conversation_id str

Conversation identifier for tracing.

''
**kwargs Any

Extra parameters forwarded to LiteLLM.

{}

Returns:

Type Description
str

The assistant's response text.

complete_with_tools async

complete_with_tools(messages: list[dict[str, str]], tools: list[dict[str, Any]], *, conversation_id: str = '', **kwargs: Any) -> dict[str, Any]

Send a chat completion with tool/function definitions.

Parameters:

Name Type Description Default
messages list[dict[str, str]]

Chat messages in OpenAI format.

required
tools list[dict[str, Any]]

Tool definitions (OpenAI function calling schema).

required
conversation_id str

Conversation identifier for tracing.

''
**kwargs Any

Extra parameters forwarded to LiteLLM.

{}

Returns:

Type Description
dict[str, Any]

The full response dict including any tool calls.

Capability

Enum identifying what a connector can do. Used by ConnectorRegistry.find_by_capability(...) for capability-based dispatch (the agent and workflow engine both rely on this to discover available actions at runtime).

Capability

Bases: StrEnum

Actions a connector can perform, declared at registration.

Membership in a connector's capabilities frozenset grants permission for the agent/MCP layer to invoke the corresponding method. String values are stable wire identifiers — do not change them without a deprecation cycle.

Citations

When the agent answers a question from retrieved documents it returns a structured AgentResponse carrying inline citations alongside the prose answer. Each Citation references a chunk_id produced by DocumentStoreConnector.search() so callers can audit which exact passage drove the answer.

AgentResponse

Bases: BaseModel

Structured agent output carrying text and grounded citations.

Attributes:

Name Type Description
text str

The rendered answer, carrying inline [n] citation markers renormalized to 1..N at egress (the trailing <citations> block is stripped).

citations list[Citation]

List of source citations, one per chunk the agent relied on, in display order: citations[0] corresponds to the inline [1] marker (numbered by first appearance in the prose; citations referenced only in the <citations> block are appended after the inline ones). May be empty when the answer is not grounded in documents.

is_fallback bool

True when text is a synthetic fallback the runtime substituted because the LLM returned no usable output (an empty completion or a citations-only block), not a real model answer. Lets programmatic callers and monitors tell a genuine response apart from a degraded one.

completeness Literal['complete', 'partial']

"partial" when the runtime was forced to finalize the turn before the agent could confirm it had retrieved everything (a no-progress / suppressed-read break), so the answer may be incomplete; "complete" otherwise. Distinct from is_fallback — a partial answer is a real model answer that may be missing data, not a synthetic non-answer. Monitors that count fallbacks must not treat a partial answer as degraded.

Citation

Bases: BaseModel

A pointer from an answer back to its source chunk.

Attributes:

Name Type Description
chunk_id str

Deterministic identifier of the source chunk (matches :attr:DocumentChunk.chunk_id).

source str

Source file path or document name.

page int

Page number, when known. 0 means "no page".

quote str

Optional short verbatim excerpt the claim is grounded in.

confidence float

Optional confidence score in [0.0, 1.0].

Example
Citation(chunk_id="abc123", source="manuals/pump.pdf", page=42)

inline_marker

inline_marker() -> str

Render a compact inline marker like [source:page].

Note

:attr:AgentResponse.text now carries numeric [n] markers renormalized at egress; this [source:page] format is used nowhere in the rendered text. Kept for backward compatibility.