Skip to main content
Machina

Machina

Build AI agents for industrial maintenance in a few lines of Python.

License: Apache 2.0 Python 3.11+ PyPI version CI Downloads DOI

Quick Start • Examples • Why Machina • Docs • Contributing


Machina demo
Installing the Machina agent-builder plugin in Claude Code

Quick Start

pip install machina-ai[litellm,docs-rag]
git clone https://github.com/LGDiMaggio/machina.git
cd machina/examples/quickstart
python agent.py

LLM provider required. Choose one:

Provider Setup
Ollama (local, free) Install from ollama.com, then ollama pull llama3
OpenAI export OPENAI_API_KEY=sk-...
Anthropic export ANTHROPIC_API_KEY=sk-ant-...

Override the default with python agent.py --llm openai:gpt-4o or --llm anthropic:claude-sonnet-4-20250514.

The agent is built in 13 lines:

from pathlib import Path

from machina import Agent, Plant
from machina.connectors.cmms import GenericCmmsConnector
from machina.connectors.docs import DocumentStoreConnector
from machina.connectors.comms.cli import CliChannel

SAMPLE_DIR = Path(__file__).resolve().parent.parent / "sample_data"

agent = Agent(
    name="Maintenance Assistant",
    plant=Plant(name="Demo Plant"),
    connectors=[
        GenericCmmsConnector(data_dir=SAMPLE_DIR / "cmms"),
        DocumentStoreConnector(paths=[SAMPLE_DIR / "manuals"]),
    ],
    channels=[CliChannel()],
    llm="ollama:llama3",  # or "openai:gpt-4o", "anthropic:claude-sonnet"
)
agent.run()

Sample data included: 6 assets, 5 work orders, 6 spare parts, 10 failure modes, 2 equipment manuals. Your technicians can now talk to their plant data. An example session, abridged (the wording depends on the model):

You: What is the bearing replacement procedure for pump P-201?

Agent: From the Grundfos CR 32-2 manual for P-201 [1]:
1. Lock out / tag out the motor and verify zero energy state
2. Disconnect the coupling, remove the bearing housing covers (4x M12 bolts)
3. Pull the old bearings; clean the shaft journals and inspect for scoring
4. Heat the new bearings to 110 °C with an induction heater and slide them on
5. Let them cool naturally; pack the housings with SKF LGMT 3 grease
6. Refit the covers (80 Nm, star pattern), check alignment, reconnect the coupling
7. Start up and verify: vibration < 2.5 mm/s, bearing temperature < 60 °C after 1 h
Parts: 2x SKF 6310 bearing (4 in stock).

— Sources:
  • [1] pump_p201_manual.md

You: Are there open work orders on that pump?

Agent: Yes, two on P-201, both in status "created":
  WO-2026-1842 | corrective | high   | Excessive vibration on the DE bearing, probable bearing wear
  WO-2026-1840 | preventive | medium | Quarterly pump inspection

You: Create a work order for bearing replacement on P-201, priority HIGH

⚠️  Create a work order?
  • Asset: P-201
  • Type: corrective
  • Priority: high
  • Description: Replace the drive-end bearings (SKF 6310) following the manual procedure; elevated vibration on the drive-end bearing.
Confirm? [y/N] y

Agent: Created work order WO-AUTO-0B2E8887 on P-201 (corrective, priority high).

The agent resolves "pump P-201" to the actual asset, retrieves its work orders and spare parts from your CMMS, searches the manuals via RAG (with citations), and asks before it writes anything. Answer quality depends on the model: small local models (8B) are noticeably less reliable -- in test runs they sometimes returned a tool instruction instead of an answer, or misread the retrieved context -- so use a hosted or larger model when accuracy matters.

Try it now: cd examples/quickstart && python agent.py -- full quickstart guide

Now Make It Automate

Add one line to register a workflow. The agent handles alarms end-to-end:

from machina.workflows.builtins import alarm_to_workorder

agent = Agent(
    connectors=[cmms, docs],
    workflows=[alarm_to_workorder],  # alarm → diagnosis → WO → notify
    sandbox=True,
)
  Alarm:  ALM-2026-0412-001  |  Asset: P-201
  vibration_velocity_mm_s = 7.8 (threshold: 6.0)

  Result: SUCCESS (0.00s)
    [+] analyze_alarm        BEAR-WEAR-01 (medium), IMP-EROSION-01 (medium), BELT-WEAR-01 (medium)
    [+] check_history        none
    [+] check_spare_parts    SKF-6310 (stock 4), SEAL-CR32-KIT (stock 1)
    [+] generate_work_order  WO-AUTO-3B717CA0: corrective, priority medium, failure mode BEAR-WEAR-01
    [+] notify_technician    sandbox: intercepted, not executed
    [+] submit_work_order    sandbox: intercepted, not executed

6 steps, all deterministic -- domain services and connector calls, no LLM call -- so they are fast, predictable and testable; in sandbox mode the notification and the CMMS submit are intercepted. Try it: cd examples/alarm_to_workorder && python agent.py -- full guide

Or configure via YAML

For knowledge-base agents (Q&A over CMMS data, manuals, spare parts), you can skip Python entirely and configure via YAML:

name: "Maintenance Assistant"
plant:
  name: "North Plant"
connectors:
  cmms:
    type: generic_cmms
    settings:
      data_dir: "./sample_data/cmms"
  docs:
    type: document_store
    settings:
      paths: ["./sample_data/manuals"]
channels:
  - type: cli
llm:
  provider: "ollama:llama3"
from machina import Agent

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

YAML config is ideal for knowledge-base agents — technician Q&A, document search, asset lookup. For agents with automated workflows (alarm response, predictive pipelines), use Python — workflows need logic (guards, error policies, LLM reasoning steps) that YAML can't express. See the YAML config guide for details.

What You Can Build

Two examples take you from zero to automation. Then deploy with the starter kit.

Step Example What happens
1. Understand quickstart/ Agent answers questions about equipment, procedures, spare parts, maintenance history
2. Automate alarm_to_workorder/ Alarm fires -- agent diagnoses failure, checks parts, creates work order, notifies team
3. Deploy odl-generator-from-text/ Free-text requests become confirmed Work Orders in a spreadsheet (or REST CMMS). Starter kit, sandbox-first

The LLM-driven examples default to ollama:llama3 -- local, free, no API key needed. Override: --llm openai:gpt-4o. The alarm workflow needs no LLM at all.

More patterns in examples/reference/: predictive pipelines, CMMS portability, custom workflows, YAML config, autonomous agents.

Starter Kit

Ready to adapt? The odl-generator-from-text template is a copy-configure-run starter kit:

cp -r templates/odl-generator-from-text my-agent
cd my-agent
pip install "machina-ai[excel,litellm,examples]"
cp .env.example .env        # set your LLM model and key
python agent.py --sandbox   # or: docker compose run --rm machina

A technician describes a problem in their language:

Italian: "pompa P-201 perde acqua, caldaia C-3 rumore anomalo, prego creare OdL" English: "pump P-201 leaking water, boiler C-3 abnormal noise, please create WO"

The agent resolves the assets against the registry, proposes one work order per asset, and — in live mode, after you confirm each one — appends them to a spreadsheet or a REST CMMS. Full template guide →

Build with Claude Code

Machina ships a Claude Code plugin — machina-agent-builder — that makes the framework LLM-buildable. Instead of wiring an agent by hand, you drive two slash commands and Claude reads Machina's code-derived self-description spine (machina describe) to assemble a working agent from what the framework actually supports:

  • /build-machina-agent — reads the spine, confirms the shape with you, then generates a config.yaml + entrypoint wiring only the capabilities the spine reports as backed.
  • /extend-machina — adds a connector, capability, MCP tool, mapper, or workflow against the seam the spine declares, then regenerates the spine so the CI drift gate stays green.

Because both commands consume the live spine rather than a hardcoded list, the plugin never goes stale as Machina changes. The repo doubles as a Claude Code plugin marketplace, so installing it is two slash commands:

/plugin marketplace add LGDiMaggio/machina
/plugin install machina-agent-builder@machina
Installing the Machina agent-builder plugin in Claude Code

Prerequisite — the commands run machina describe, so machina-ai must be installed in the environment where you use the plugin. See the plugin guide for the full walkthrough (local-checkout install, why it stays in sync).

From Demo to Production

The quickstart uses sample data. When you're ready, swap connectors to your real systems -- the agent logic doesn't change:

# Demo (quickstart)                              # Production
GenericCmmsConnector(data_dir="./sample/")  -->   SapPM(url="https://sap.company.com/odata/v4", auth=...)
                                                  Maximo(url="https://maximo.company.com/oslc", auth=...)
DocumentStoreConnector(paths=["./manuals/"])-->   DocumentStoreConnector(paths=["/shared/manuals/"])
CliChannel()                               -->   Telegram(bot_token="...")
"ollama:llama3"                            -->   "openai:gpt-4o"

Add sensors when you need predictive maintenance:

from machina.connectors import OpcUA, MQTT

agent = Agent(
    connectors=[cmms, docs, OpcUA(endpoint="opc.tcp://plc:4840", ...)],
    workflows=[alarm_to_workorder],
    llm="openai:gpt-4o",
)

Same agent, same workflows. Just more data flowing in.

Why Machina?

Building an AI maintenance agent today means writing custom connectors for SAP PM, handling OPC-UA subscriptions, defining domain concepts from scratch, and engineering prompts that understand maintenance -- before writing a single line of business logic. That takes months.

Machina provides the missing vertical layer between general-purpose frameworks (LangChain, CrewAI) and the industrial maintenance world:

  • Pre-built connectors for CMMS, IoT sensors, communication platforms, and document stores
  • Canonical maintenance domain model -- Asset, WorkOrder, FailureMode, SparePart, Alarm with hierarchies and validation
  • Domain-aware AI -- agents that resolve equipment references, inject maintenance context, and ground answers in real data
  • Rule-based + LLM intelligence -- deterministic services (FailureAnalyzer, WorkOrderFactory, MaintenanceScheduler) work alongside the LLM, not instead of it
  • Workflow engine -- composable multi-step workflows with error policies, guard conditions, and sandbox mode
  • LLM-agnostic -- OpenAI, Anthropic, Mistral, Llama, Ollama, and any LiteLLM-compatible provider
  • Sandbox mode -- test everything safely with a log-only runtime before connecting real systems

How It Works Under the Hood

When a user asks "What's wrong with pump P-201?", the agent:

  1. Resolves entities -- "the pump" or "P-201" maps to the actual Asset in the registry, with its failure modes and criticality; when the match is weak or ambiguous, the agent asks which asset you mean instead of guessing
  2. Gathers context -- once the asset is resolved, its work orders, compatible spare parts and relevant manual excerpts (RAG) are fetched concurrently, each from the first connector that provides it
  3. Grounds the LLM -- the retrieved context (real asset data, real inventory, real history) is injected into the prompt, so the LLM reasons over your data rather than its guesses
  4. Takes action -- the LLM calls tools for look-ups, diagnosis and work-order creation; every write asks for your confirmation by default and is a no-op in sandbox mode. Workflows run the same kind of work as fixed steps -- rule-based diagnosis, spare-part checks, work-order drafting -- and can add LLM reasoning steps where judgment is needed
Connector Matrix

CMMS

Connector System
GenericCmms Any REST-based CMMS (configurable via schema mapping) Available
SapPM SAP Plant Maintenance (OData v2/v4, OAuth2 + Basic Auth) Available
Maximo IBM Maximo (OSLC/JSON, API key + Basic + Bearer) Available
UpKeep UpKeep CMMS (REST API v2, Session-Token) Available
MaintainX MaintainX Planned
Limble Limble CMMS Planned
Fiix Fiix (Rockwell) Planned

Spreadsheets & Databases

Connector Source
ExcelCsvConnector Excel (.xlsx) and CSV files, mapped column by column Available
GenericSqlConnector SQL databases over ODBC/JDBC, mapped query by query Available

IoT & Industrial Protocols

Connector Protocol
OpcUA OPC-UA Available
MQTT MQTT / Sparkplug B (JSON payloads only -- protobuf needs an MQTT-to-JSON bridge) Available
Modbus Modbus TCP/RTU Planned

Communication & Scheduling

Connector Platform
Telegram Telegram Bot API Available
Slack Slack Bolt SDK (Socket Mode) Available
Email SMTP / IMAP (+ Gmail API) Available
Calendar Google Calendar / Outlook / iCal Available
WhatsApp WhatsApp Business Cloud API Planned
Teams Microsoft Graph API Planned

Documents & Knowledge

Connector Source
DocumentStore PDF / DOCX with RAG (LangChain + ChromaDB) Available

Architecture

                    +---------------------------+
                    |   Claude / Cursor / MCP   |
                    +-------------+-------------+
                                  | MCP Protocol
+------------------------------------------------------+
|              YOUR APPLICATION                         |
|  +---------------------+  +------------------------+ |
|  |    AGENT LAYER       |  |    MCP SERVER LAYER    | |
|  | Runtime + Workflows  |  |  (tools gated by       | |
|  | Domain Prompting     |  |   connector caps)      | |
|  +----------+-----------+  +-----------+------------+ |
+-----------+----------------------------+--------------+
|                    DOMAIN LAYER                        |
|  Asset . WorkOrder . FailureMode . SparePart . Alarm  |
+-------------------------------------------------------+
|                  CONNECTOR LAYER                       |
|  CMMS . Excel/SQL . IoT . Messaging . Documents       |
+-------------------------------------------------------+
|                    CORE LAYER                          |
|      LLM Abstraction . Config . Observability         |
+-------------------------------------------------------+
Domain Model

Building Maintenance AI Agents: before and after Machina

The domain model is the backbone of Machina. Every connector normalizes external data into domain entities, the agent reasons in domain terms, and LLM prompts are grounded in domain context.

Why this matters:

  • Portability -- Switch CMMS backends, your agent logic doesn't change
  • Deterministic logic where it counts -- FailureAnalyzer, WorkOrderFactory, MaintenanceScheduler encode expertise as code, not LLM guesses
  • LLM grounding -- the LLM works with real, validated data (failure codes, maintenance history, inventory levels), not hallucinated IDs
  • Industry-aligned taxonomy -- failure modes and equipment classes follow established industrial standards
from machina.domain import Asset, AssetType, FailureMode

pump = Asset(
    id="P-201",
    name="Cooling Water Pump",
    type=AssetType.ROTATING_EQUIPMENT,
    criticality="A",
    equipment_class_code="PU",  # ISO 14224 Table A.4
)

bearing_wear = FailureMode(
    code="BEAR-WEAR-01",
    iso_14224_code="VIB",       # ISO 14224 Annex B Table B.15
    name="Bearing Wear",
    mechanism="fatigue",
    typical_indicators=["vibration_velocity_mm_s", "bearing_temperature_c"],
    recommended_actions=["replace_bearing", "check_alignment"],
)

The full domain includes: Asset (hierarchical trees), WorkOrder (lifecycle management), FailureMode (ISO 14224 taxonomy), SparePart (inventory tracking), Alarm (severity-based), MaintenancePlan (scheduling), plus three domain services that provide rule-based intelligence alongside the LLM.

Workflow Engine

Build multi-step maintenance workflows that mix deterministic steps with LLM reasoning:

from machina.workflows import Workflow, Step, Trigger, TriggerType, ErrorPolicy

alarm_to_workorder = Workflow(
    name="Alarm to Work Order",
    trigger=Trigger(type=TriggerType.ALARM, filter={"severity": ["critical"]}),
    steps=[
        Step("diagnose", action="failure_analyzer.diagnose",
             on_error=ErrorPolicy.STOP),
        Step("check_history", action="cmms.read_maintenance_history",
             inputs={"asset_id": "{trigger.asset_id}"},
             on_error=ErrorPolicy.SKIP),
        Step("create_wo", action="work_order_factory.create",
             on_error=ErrorPolicy.STOP),
        Step("notify", action="channels.send_message",
             template="WO created for {trigger.asset_id}: {diagnose}",
             on_error=ErrorPolicy.NOTIFY),
    ],
)

agent = Agent(workflows=[alarm_to_workorder], sandbox=True)
result = await agent.trigger_workflow("Alarm to Work Order", {"asset_id": "P-201"})

Or use the built-in template: from machina.workflows.builtins import alarm_to_workorder

Features: error policies (retry/skip/stop/notify), guard conditions, template variables ({trigger.*}, {step_name}), sandbox mode, and step tracing via ActionTracer. A workflow's trigger (alarm, schedule, manual, condition) describes the event it handles; you start a run with agent.trigger_workflow(...), or the agent does through its execute_workflow tool.

MCP Server

Expose your connectors as an MCP server -- let Claude Desktop, Cursor, or any MCP client query your CMMS, spreadsheets and manuals directly:

pip install "machina-ai[mcp]"
machina mcp serve --config machina.yaml

Ask Claude: "What's the maintenance history for pump P-201?" -- and it queries your CMMS (SAP PM, Maximo, UpKeep, a REST API or a spreadsheet) through Machina's MCP server. No agent code required.

The server registers tools only for the capabilities your connectors declare (15 domain tools, plus 2 opt-in vendor tools), together with 4 resources and 3 prompt templates. It runs over stdio for a local client, or over streamable HTTP with bearer-token auth for shared deployments; writes respect sandbox mode. See the MCP docs.

Roadmap

v0.1 -- Core domain model, CMMS connectors (SAP PM, Maximo, UpKeep), DocumentStore with RAG, Telegram, Agent runtime, CI/CD

v0.2 -- Workflow engine, IoT connectors (OPC-UA, MQTT), Slack, Email, Calendar, sandbox mode, security hardening

v0.3 -- MCP server layer, typed connector capabilities, Excel/CSV and SQL substrates, Generic CMMS YAML mapper, deployment story, starter kit; v0.3.1 added write-path safety and the RAG upgrade

v0.4 (current) -- Runnable MCP server (machina mcp serve, stdio and streamable HTTP), human-in-the-loop write confirmation and resolution-authority gates, failure-mode catalogs as a capability, YAML-buildable substrates, documentation checked against the code

v0.5 (next) -- MaintainX/Limble/Fiix connectors, WhatsApp and Teams, anomaly detection and RUL estimation, multi-agent orchestration

Details in the roadmap and the changelog.

Citing Machina

If you use Machina in your research, please cite the software:

@software{dimaggio_machina_2026,
  author    = {Di Maggio, Luigi Gianpio},
  title     = {{Machina: An AI Agent Framework for Industrial Maintenance}},
  version   = {0.4.0},
  year      = {2026},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.19456867},
  url       = {https://github.com/LGDiMaggio/machina}
}

10.5281/zenodo.19456867 is the concept DOI: it always resolves to the latest version, and the Zenodo record lists the DOI of each release for citing a specific one. GitHub's "Cite this repository" button reads CITATION.cff.

Contributing

We welcome contributions! See CONTRIBUTING.md for the full guide.

git clone https://github.com/LGDiMaggio/machina.git
cd machina
pip install -e ".[dev,all]"
make ci   # lint + typecheck + spine drift check + tests

Community & Support

License

Apache License 2.0. See LICENSE.

Acknowledgments

LiteLLM | LangChain | asyncua | ChromaDB | structlog | MCP SDK

Metadata

Release files for machina-ai 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for machina-ai 0.4.0
File Size Uploaded
machina_ai-0.4.0.tar.gz 42.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for machina-ai 0.4.0
File Interpreter ABI Platform
machina_ai-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 42.6 MB

Release files / machina_ai-0.4.0.tar.gz

Download URL machina_ai-0.4.0.tar.gz
Size 42.2 MB
Tags Source
SHA-256 checksum
How to use checksums
42204fde392737b7766c7a25ede9cf223327d9ffff04908715eb30e55eff19bb
BLAKE2b-256 checksum
How to use checksums
353291afaef791ee1683ffd5f816ece6119ed00a813b19c5e2abbd724c5f80af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release files / machina_ai-0.4.0-py3-none-any.whl

Download URL machina_ai-0.4.0-py3-none-any.whl
Size 350.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cb2e4b8629aca180f063d559d78d574ec954611afd22360041e7695e6d84dc83
BLAKE2b-256 checksum
How to use checksums
e37e7a9f2d1983ce184f49b8f97078943a59f1b3c47fd479ed3084c11b73addd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.16

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page