An open, Apache-2.0 taxonomy for classifying what AI agents are trying to do — across software, enterprise systems, and physical / embodied machines.
Open Intent (OI) is a stable, vendor-neutral vocabulary of action intents. Every action an agent might take — deploying code, processing an invoice, granting access, picking a workpiece, navigating to a waypoint, executing a surgical primitive — maps to a stable code such as OI-101 or OI-1502. Once an action has an OI code, any system can reason about it the same way, regardless of which agent, runtime, or vendor produced it.
"deploy checkout to prod" ┐
POST /api/v2/deployments │
gh.actions.workflow_run.completed │ classify
k8s.deployment.apps/v1.update ├───────────────▶ OI-104 (Deployment & Release)
terraform apply -auto-approve │ OI-1502 (Pick & Place)
ros2:action:moveit_msgs/Pick │ OI-2902 (Geofencing)
px4:command/MAV_CMD_NAV_TAKEOFF │
opcua:method/siemens.tia/MoveAxis ┘
many shapes · many vendors · many runtimes ─────▶ one stable vocabulary
AI agents act through a sprawl of incompatible surfaces — REST calls, webhooks, Kubernetes objects, Terraform plans, ROS 2 action goals, OPC-UA method invocations, MAVLink commands. Each names the same kind of action differently. Without a shared vocabulary:
- Authorization policies don't travel. A rule about "deployments" has to be re-expressed for every platform's naming.
- Audit evidence is fragmented. "What did the agent do?" has a different answer format per vendor.
- Safety reasoning is platform-specific. "Does this action touch a safety-rated function?" can't be asked generically.
Open Intent gives you one stable code per kind of action. OI-104 means "deployment" whether it arrived as a GitHub Actions event, a kubectl apply, or a Terraform run. That single code is what your authorization, audit, and policy layers reference — so the policy is written once and the audit trail is uniform.
Open Intent is only the vocabulary. It does not classify, authorize, or enforce anything on its own — it is the shared set of codes that classifiers and policy engines agree to use. See Using it in a runtime.
Open Intent is a two-level tree: domains (broad areas of activity, coded OI-100, OI-200, ... OI-2900) each containing a set of categories (specific kinds of action, coded OI-101, OI-102, ...).
29 domains · 173 categories — split into digital and physical / embodied operations.
| Code | Domain | Categories |
|---|---|---|
| OI-100 | Software Development | 7 |
| OI-200 | Security Operations | 7 |
| OI-300 | Infrastructure | 7 |
| OI-400 | Cloud Operations | 6 |
| OI-500 | Financial Operations | 8 |
| OI-600 | Supply Chain | 5 |
| OI-700 | People Operations | 6 |
| OI-800 | Revenue Operations | 5 |
| OI-900 | Customer Experience | 5 |
| OI-1000 | Enterprise Operations | 6 |
| OI-1100 | Service Delivery | 4 |
| OI-1200 | Risk Management | 5 |
| OI-1300 | Product Operations | 4 |
| OI-1400 | Asset Management | 5 |
| Code | Domain | Categories |
|---|---|---|
| OI-1500 | Manipulation | 6 |
| OI-1600 | Locomotion & Mobility | 6 |
| OI-1700 | Sensing & Perception | 7 |
| OI-1800 | Actuation & Control | 5 |
| OI-1900 | Manufacturing & Production | 7 |
| OI-2000 | Autonomous Vehicles | 7 |
| OI-2100 | Aerial Systems | 6 |
| OI-2200 | Surgical & Medical Robotics | 7 |
| OI-2300 | Agricultural Operations | 6 |
| OI-2400 | Construction & Excavation | 6 |
| OI-2500 | Hazardous Environments | 6 |
| OI-2600 | Energy & Utilities | 6 |
| OI-2700 | Mining & Resource Extraction | 5 |
| OI-2800 | Logistics & Material Handling | 6 |
| OI-2900 | Embodied AI Safety | 7 |
These counts are the ground truth in
src/oi-taxonomy.json. You can reproduce them from the data — see Verifying the counts.
OI-2900 Embodied AI Safety collects the safety-primitive categories that physical-AI policies most often need to reason about:
| Code | Category |
|---|---|
| OI-2901 | Emergency Stop |
| OI-2902 | Geofencing |
| OI-2903 | Human-Presence Detection |
| OI-2904 | Safety-Rated Motion |
| OI-2905 | Lockout / Tagout |
| OI-2906 | Collision Avoidance |
| OI-2907 | Compliance & Certification |
A policy engine can treat the OI-2900 range as "safety-relevant" without knowing anything about the specific vertical (agriculture vs. surgery vs. mining), because every vertical maps its safety-critical actions onto these shared codes.
- Domains end in
00:OI-100,OI-200, ... up toOI-2900. - Categories sit under their domain:
OI-101...OI-107belong toOI-100. - A category's parent domain is found by replacing the last two digits with
00(e.g.OI-1502→OI-1500). - Within a major version, codes are append-only — they are never renumbered or reused. You can hard-code an
OIcode and trust it stays meaning the same thing.
Each entry carries a code, a human-readable name, and a description. Example from the data:
{
"code": "OI-1502",
"name": "Pick & Place",
"description": "Workpiece transfer, fixture loading and unloading, bin picking, and kitting."
}The taxonomy ships as an npm package with TypeScript types and lookup helpers:
npm install @intended-inc/open-intent # or pnpm add @intended-inc/open-intent # or yarn add @intended-inc/open-intent
The published package is @intended-inc/open-intent .
The taxonomy data is just JSON. If you work in another language, you don't need the npm package — consume
src/oi-taxonomy.jsondirectly (vendor the file, or fetch it from this repo). The schema is documented under The data file.
import { oi, domains, getDomain, getCategory, getDomainForCategory, allCategoryCodes, } from "@intended-inc/open-intent"; // Look up a category by code const cat = getCategory("OI-1502"); // { code: "OI-1502", name: "Pick & Place", // description: "Workpiece transfer, fixture loading and unloading, bin picking, and kitting." } // Find the domain a category belongs to const parent = getDomainForCategory("OI-1502"); // { code: "OI-1500", name: "Manipulation", description: "...", categories: [...] } // Look up a domain directly const dom = getDomain("OI-1500"); // { code: "OI-1500", name: "Manipulation", ... } // Enumerate everything allCategoryCodes().length; // 173 domains.length; // 29 oi.version; // "2.0" (the taxonomy schema version)
| Export | Type | Description |
|---|---|---|
oi |
OiTaxonomy |
The full taxonomy object (version, name, abbreviation, domains). Also the default export. |
domains |
OiDomain[] |
All 29 domains, each with its categories. |
getDomain(code) |
OiDomain | undefined |
Look up a domain by code, e.g. "OI-1500". |
getCategory(code) |
OiCategory | undefined |
Look up a category by code, e.g. "OI-1502". |
getDomainForCategory(code) |
OiDomain | undefined |
Get the parent domain for a category code. |
allCategoryCodes() |
string[] |
Every category code (173 of them). |
Note on versions. The npm package version (currently
2.1.0in this repo) tracks releases of the package and docs. The taxonomy schema version exposed asoi.versionis"2.0"— it changes only when the set of domains/categories changes. They are intentionally independent.
Open Intent is the vocabulary, not the engine. A typical integration looks like this:
1. Agent emits a native action 2. You classify it 3. You act on the code
(REST / k8s / ROS 2 / MAVLink) to an OI code in your own policy layer
"terraform apply" ──▶ OI-104 ──▶ authorize(OI-104)?
ros2:action:.../Pick ──▶ OI-1502 ──▶ in OI-2900 range? require review
px4:.../NAV_TAKEOFF ──▶ OI-2101 ──▶ audit-log the OI code
You bring (or build) the classifier and the policy engine. Open Intent only guarantees that step 2's output is a stable code both ends agree on — so the same policy and the same audit format work no matter which runtime produced the action.
Mapping a native action to an OI code is a decision you make (a lookup table, a rule, or a model). This package does not ship a classifier; it ships the target vocabulary that a classifier resolves to.
Open Intent is maintained by Intended. Intended also offers a commercial Authority Runtime that builds on this taxonomy with classification, a policy DSL, an audit chain, signed authority tokens, and an edge verifier. The relationship is the familiar open-standard / commercial-implementation split (think Linux + a distribution, or OAuth + an identity provider).
- Platform overview: https://intended.so/platform
- Physical-AI integration: https://intended.so/physical-ai
You can adopt Open Intent on its own — it is Apache-2.0 and carries no dependency on the runtime.
src/oi-taxonomy.json is the canonical source. Shape:
{
"version": "2.0",
"name": "Open Intent",
"abbreviation": "OI",
"description": "...",
"domains": [
{
"code": "OI-100",
"name": "Software Development",
"description": "...",
"categories": [
{ "code": "OI-101", "name": "Code Management", "description": "..." }
// ...
]
}
// ...
]
}The npm package re-exports this same file at @intended-inc/open-intent/taxonomy.json.
The figures in this README are reproducible from the data:
node -e 'const t=require("./src/oi-taxonomy.json"); console.log(t.domains.length, "domains"); console.log(t.domains.reduce((n,d)=>n+d.categories.length,0), "categories");' # → 29 domains # → 173 categories
Open Intent follows Semantic Versioning at the package level. The taxonomy itself is append-only within a major version: codes are never renumbered or reused, so existing integrations never break on a minor or patch bump.
| Taxonomy version | Domains | Categories | Notes |
|---|---|---|---|
| 2.0 (current) | 29 | 173 | Adds the 15-domain physical / embodied expansion (OI-1500–OI-2900) on top of v1.0. |
| 1.0 | 14 | 80 | Digital operations only (OI-100–OI-1400). Stable; consumers should move to v2. |
The v2.0 → v2.1 package release was a metadata-only rename (the standard was formerly named "Open Intent Layer"); no codes, categories, or APIs changed. See CHANGELOG.md for the full history.
Taxonomy changes — new domains, new categories, clarified descriptions — are welcome. Please read CONTRIBUTING.md before opening a PR. In short:
- Open an Issue describing the change and the real agent action that needs it.
- Propose the OI code (the next free code in the appropriate domain range).
- Send a PR with the taxonomy edit and a
CHANGELOG.mdentry.
Apache License 2.0. Copyright © Intended, Inc.