You know how to ride a bicycle. You know how to make coffee. You know how to deploy a new release to production. These are all examples of procedural memory — knowing how to do something, as opposed to knowing what is true.
In the Open Memory Specification, procedural memory is captured by the Workflow memory type. Defined in Section 8.4, a Workflow is a directed graph of procedural steps — plans, pipelines, and multi-path processes. Real procedures branch, fan out, wait on multiple predecessors, and retry. OMS v1.4 redesigned the type to say so directly: the flat steps array of earlier revisions was replaced by a graph of nodes and edges.
This post covers the Workflow memory type in depth: the graph model, how structure is inferred from topology rather than declared, node-to-Tool binding, how agents learn workflows from patterns, versioning through supersession, serialization details, and practical use cases across industries.
What is a Workflow?
The spec defines a Workflow as:
Directed graph of procedural steps — plans, pipelines, and multi-path processes.
A Workflow has one required structural component — a set of nodes — and three optional ones: the edges connecting them, the bindings that attach nodes to concrete tools, and the retries that bound repetition. An optional trigger describes when the procedure should activate.
The graph model matters because the alternative degrades badly. A flat ordered list can only express "do A, then B, then C." It cannot express "run the security scan and the compliance check in parallel, wait for both, then branch on the approval decision, retrying the staging deploy up to three times." Encoding that in a list means smuggling control flow into step text, where no implementation can read it reliably.
Workflows can be authored by humans, but they can also be extracted from observed patterns in an agent's behavior. When an agent notices that it keeps performing the same sequence of tool calls in response to the same kind of situation, that pattern can be formalized as a Workflow grain and reused.
Required Fields
The Workflow type has three required fields (Section 8.4):
| Field | Type | Description |
|---|---|---|
type | string | Must be "workflow" |
nodes | array[string] | Non-empty array of graph node identifiers, unique within the grain |
created_at | int64 | Creation timestamp in epoch milliseconds |
Each element of nodes serves as both the node's ID and its human-readable label — there is no separate label field to keep in sync. Node IDs must be unique within the grain.
Note what is not required: trigger. A Workflow is a plan, and a plan is meaningful whether or not anything fires it automatically. In earlier OMS revisions trigger was mandatory; since v1.4 it is optional.
Here is a minimal Workflow — a linear pipeline:
{
"type": "workflow",
"trigger": "merge to main",
"nodes": ["build", "test", "deploy"],
"edges": [
{"src": "build", "dst": "test"},
{"src": "test", "dst": "deploy"}
],
"created_at": 1768471200000
}The header byte for Workflow is 0x04 (Section 3.1.1, Type enum), so this grain's 9-byte fixed header would begin with 01 00 04 — version 1, no flags set, Workflow type.
Optional Fields
| Field | Type | Description |
|---|---|---|
trigger | string | Condition that activates this workflow |
edges | array[map] | Directed edges between nodes. When absent, nodes are unconnected |
bindings | map[string→string] | Maps node IDs to Tool definition grain hashes |
retries | map[string→int] | Maps node IDs to a maximum repeat count on failure |
Workflows also inherit the common optional fields available to all grain types through the core field map (Section 6.1) — author_did, user_id, namespace, importance, structural_tags, derived_from, provenance_chain, related_to, and the rest.
The Edge Schema
Each element of edges is a map with two required fields and two optional ones:
| Field | Type | Required | Description |
|---|---|---|---|
src | string | yes | ID of the source node (must exist in nodes) |
dst | string | yes | ID of the target node (must exist in nodes) |
cond | string | no | Opaque condition string; absent means unconditional |
max_cycles | int | no | Maximum traversal count for back-edges; absent means unlimited |
Like trigger, cond is an opaque string, not an expression the format evaluates. OMS is a data format, not an execution engine.
Structure Is Inferred, Never Declared
This is the most important design decision in the redesigned type: node roles come from graph topology, not from a declared node-type field.
| Topology | Inferred role |
|---|---|
| Multiple outgoing unconditional edges | Parallel fan-out (fork) |
| Target of multiple edges | AND-join — all predecessors must complete |
Multiple outgoing conditional edges (cond present) | Decision point |
| No outgoing edges | Terminal node |
First element of nodes | Entry point |
Back-edges — edges that form cycles — are permitted when bounded by max_cycles or by an entry in retries.
Here is a fork/join in practice — two review gates that run in parallel, both of which must finish before evaluation:
{
"type": "workflow",
"trigger": "PR opened",
"nodes": ["lint", "security", "compliance", "evaluate"],
"edges": [
{"src": "lint", "dst": "security"},
{"src": "lint", "dst": "compliance"},
{"src": "security", "dst": "evaluate"},
{"src": "compliance", "dst": "evaluate"}
],
"created_at": 1768471200000
}lint has two outgoing unconditional edges, so it forks. evaluate is the target of two edges, so it is an AND-join. No field says either of those things.
Validation Constraints
An implementation validating a Workflow grain checks (Section 8.4):
- Every
srcanddstinedgesMUST reference an element ofnodes. - Every key in
bindingsMUST reference an element ofnodes. - Every key in
retriesMUST reference an element ofnodes. - Node IDs MUST be unique within
nodes. - Unbounded cycles — a back-edge with no
max_cyclesand noretriesentry for the target node — SHOULD be rejected.
That last constraint is the one worth dwelling on. A cycle without a bound is a procedure that may never terminate. The spec does not forbid cycles, because retry loops and iterative refinement are legitimate procedures; it requires that they be bounded.
Node-to-Tool Binding
A node is a step. What actually runs it? OMS defines a three-tier resolution:
| Tier | Condition | Resolution |
|---|---|---|
| Bound | Node ID present in bindings | Fetch the Tool definition grain by hash; use its tool_name, input_schema, output_schema |
| Named | No binding, but a Tool definition grain exists with a matching tool_name | Resolve by convention (implementation-defined lookup) |
| Abstract | No binding, no matching tool | The node label is a human-readable instruction; the executor — an LLM or agent — interprets it |
This tiering is what lets one type serve both a fully wired CI pipeline and a loosely sketched playbook. A node named "Notify the customer's account manager" needs no binding to be useful; a node named prod_deploy probably wants one.
Here is a full pipeline using conditional branching, a bounded retry, and bindings:
{
"type": "workflow",
"trigger": "release requested",
"nodes": ["build", "unit_test", "lint", "integration_test", "stage_deploy", "approval", "prod_deploy", "rollback", "notify"],
"edges": [
{"src": "build", "dst": "unit_test"},
{"src": "build", "dst": "lint"},
{"src": "unit_test", "dst": "integration_test"},
{"src": "lint", "dst": "integration_test"},
{"src": "integration_test", "dst": "stage_deploy"},
{"src": "stage_deploy", "dst": "approval"},
{"src": "approval", "dst": "prod_deploy", "cond": "approved"},
{"src": "approval", "dst": "rollback", "cond": "rejected"},
{"src": "prod_deploy", "dst": "notify"},
{"src": "rollback", "dst": "notify"}
],
"bindings": {
"build": "sha256:def111...",
"stage_deploy": "sha256:def333...",
"prod_deploy": "sha256:def444..."
},
"retries": {
"stage_deploy": 3
},
"created_at": 1711324800000
}approval has two outgoing edges, both carrying cond — a decision point. notify is reachable from either branch. stage_deploy may repeat up to three times on failure.
Execution Records Never Touch the Plan
When an agent executes a workflow node, it does not modify the Workflow grain — grains are immutable, and the plan must stay stable while runs come and go.
Instead, the agent creates a Tool grain (Section 8.5) with a relation of type mg:step_action:<node_id> targeting the Workflow grain's hash. One plan, many execution traces, all linked back by relation, none of them mutating the original.
This also means the plan and its history have separate lifecycles. You can re-run a two-year-old Workflow and the new Tool grains attach cleanly, because the Workflow's content address never moved.
Writing Workflows in CAL
Hand-writing edge arrays is tedious, so CAL — the Context Assembly Language — gives Workflows a dedicated graph syntax for ADD and SUPERSEDE rather than the usual SET clauses:
-- Simple linear workflow
ADD workflow "nightly backup"
ON "cron 0 2 * * *"
snapshot -> compress -> upload
REASON "automate database backups"
-- Parallel fork/join
ADD workflow "code review"
ON "PR opened"
lint -> (security_review, compliance_review) -> evaluate
REASON "parallel review gates"
-- Conditional branching with a bounded retry and a binding
ADD workflow "release gate"
ON "release requested"
build -> deploy * 3
deploy -> promote WHEN "healthy"
deploy -> rollback WHEN "degraded"
BIND deploy = sha256:def333...
REASON "approval-based routing"The operators map directly onto the grain fields: -> produces an edge, (a, b) produces a fork/join pair, WHEN "cond" sets cond, * N sets retries, BIND populates bindings, and ON sets trigger. Precedence runs * N (highest), then WHEN, then -> (lowest). Clause order is fixed: name → ON → graph lines → BIND → REASON.
Node names are bare identifiers or quoted strings; reserved words must be quoted. A SUPERSEDE with graph syntax replaces the graph in full rather than patching it — which is the right default for an immutable type, since a partial edit would be ambiguous about what the resulting topology is.
How Agents Learn Workflows
From Tools to Workflows
The Tool memory type (Section 8.5) records every tool invocation an agent makes: the tool name, input, content, error status, and duration. Over time, these records reveal patterns:
-
Observation: The agent (or a meta-agent) notices that in response to situation X, it consistently executes tools A, B, C — sometimes B and C concurrently.
-
Extraction: The repeated pattern is extracted as a Workflow grain whose
nodesare the recurring steps and whoseedgesencode the observed ordering and concurrency. -
Provenance: The new Workflow carries
derived_frompointing to the Tool grain content addresses that informed the pattern, andprovenance_chainentries recording the extraction method.
Because the target is a graph rather than a list, extraction can preserve something a list would flatten away: steps that were observed running concurrently stay concurrent, and steps that were observed retrying carry their bound.
{
"type": "workflow",
"trigger": "service returns 503 errors",
"nodes": [
"check_health_endpoint",
"review_deploy_history",
"inspect_pod_resources",
"check_db_pool",
"diagnose",
"scale_horizontally",
"verify_recovery"
],
"edges": [
{"src": "check_health_endpoint", "dst": "review_deploy_history"},
{"src": "check_health_endpoint", "dst": "inspect_pod_resources"},
{"src": "check_health_endpoint", "dst": "check_db_pool"},
{"src": "review_deploy_history", "dst": "diagnose"},
{"src": "inspect_pod_resources", "dst": "diagnose"},
{"src": "check_db_pool", "dst": "diagnose"},
{"src": "diagnose", "dst": "scale_horizontally", "cond": "resource_exhaustion"},
{"src": "scale_horizontally", "dst": "verify_recovery"}
],
"retries": {"verify_recovery": 3},
"created_at": 1768471200000,
"namespace": "incident-response",
"importance": 0.8,
"derived_from": [
"a1b2c3d4e5f6...",
"b2c3d4e5f6a1...",
"c3d4e5f6a1b2..."
],
"provenance_chain": [
{
"source_hash": "a1b2c3d4e5f6...",
"method": "pattern_extraction",
"weight": 0.9
}
],
"structural_tags": ["devops", "incident-response", "auto-learned"]
}The three diagnostic checks fan out from the health check and converge on diagnose — an accurate record of how a competent operator actually works, and one a flat list could not have held.
From Events to Workflows
Event grains (Section 8.2) capture raw interaction records. When multiple Events describe similar sequences of actions, consolidation can extract the common procedure as a Workflow: users describe their processes in conversation, a consolidation process identifies the repeated pattern, and the pattern becomes a graph.
Procedural vs. Declarative Memory
Understanding the distinction between Workflows and Facts is crucial for correct use of OMS memory types:
| Dimension | Workflow | Fact |
|---|---|---|
| Memory type | Procedural (knowing HOW) | Declarative (knowing WHAT) |
| Core structure | Directed graph of nodes and edges | Subject-relation-object triple |
| Purpose | Encode a procedure to follow | Encode a knowledge claim |
| Type byte | 0x04 | 0x01 |
| Required fields | 3 (type, nodes, created_at) | 6 (type, subject, relation, object, confidence, created_at) |
Has confidence | No | Yes (required, [0.0, 1.0]) |
| Standard relation | mg:has_graph | mg:knows |
The absence of a confidence field on Workflows is notable. Facts require a confidence score because they are claims that may or may not be true. Workflows are procedures — they either work or they do not. Their effectiveness is tracked through other mechanisms: the success_count and failure_count fields (available on all grains via the core field map, Section 6.1) and through supersession when an improved workflow replaces an underperforming one.
A third type sits nearby and is worth distinguishing. A Skill grain (0x0B, Section 8.11) is a packaged, transferable capability — instructions, permitted tools, bundled resources, and optional learned proficiency. A Workflow is a single fixed procedure. A Skill may reference several Workflows as context-dependent strategies: the capability is "incident triage," and the strategies are the specific graphs it runs under specific conditions.
Workflow Versioning Through Supersession
Workflows evolve. An incident response playbook gets refined after each incident. A deployment pipeline gets improved when a new tool becomes available.
In OMS, workflow evolution is modeled through supersession, not mutation. Since all grains are immutable, you cannot edit an existing Workflow. Instead, you create a new Workflow grain that supersedes the old one.
Version 1 — deploy straight to production after staging:
{
"type": "workflow",
"trigger": "new deployment to production",
"nodes": ["integration_tests", "stage_deploy", "smoke_tests", "prod_deploy", "monitor"],
"edges": [
{"src": "integration_tests", "dst": "stage_deploy"},
{"src": "stage_deploy", "dst": "smoke_tests"},
{"src": "smoke_tests", "dst": "prod_deploy"},
{"src": "prod_deploy", "dst": "monitor"}
],
"created_at": 1768471200000,
"namespace": "deployment"
}Content address: <hash-v1>
Version 2 — a canary stage is inserted, and the rollout now branches on canary health:
{
"type": "workflow",
"trigger": "new deployment to production",
"nodes": ["integration_tests", "stage_deploy", "smoke_tests", "canary", "monitor_canary", "full_rollout", "rollback", "monitor"],
"edges": [
{"src": "integration_tests", "dst": "stage_deploy"},
{"src": "stage_deploy", "dst": "smoke_tests"},
{"src": "smoke_tests", "dst": "canary"},
{"src": "canary", "dst": "monitor_canary"},
{"src": "monitor_canary", "dst": "full_rollout", "cond": "canary_healthy"},
{"src": "monitor_canary", "dst": "rollback", "cond": "canary_degraded"},
{"src": "full_rollout", "dst": "monitor"},
{"src": "rollback", "dst": "monitor"}
],
"created_at": 1768557600000,
"namespace": "deployment",
"derived_from": ["<hash-v1>"],
"provenance_chain": [
{
"source_hash": "<hash-v1>",
"method": "workflow_revision",
"weight": 1.0
}
]
}Content address: <hash-v2>
After the new grain is written, the index layer sets superseded_by: "<hash-v2>" on the v1 grain (Section 15.3). The system_valid_to timestamp is also set on v1, marking when it was replaced. Any agent looking for the current deployment workflow finds v2. But v1 is never deleted — it remains as an immutable historical record, reachable by its content address.
The derived_from and provenance_chain fields on v2 explicitly link it to v1, creating a traceable lineage. An auditor can follow the chain to see how the deployment procedure evolved, who made each change (via author_did), and when each version was active.
Industry Use Cases
IT Operations Runbooks
Runbooks are a natural fit. Most real runbooks have a diagnostic fan-out at the top — check several things at once — followed by a decision point:
{
"type": "workflow",
"trigger": "disk usage exceeds 90%",
"nodes": ["survey_usage", "check_core_dumps", "archive_old_logs", "clear_pkg_cache", "recheck", "notify_infra", "document"],
"edges": [
{"src": "survey_usage", "dst": "check_core_dumps"},
{"src": "survey_usage", "dst": "archive_old_logs"},
{"src": "survey_usage", "dst": "clear_pkg_cache"},
{"src": "check_core_dumps", "dst": "recheck"},
{"src": "archive_old_logs", "dst": "recheck"},
{"src": "clear_pkg_cache", "dst": "recheck"},
{"src": "recheck", "dst": "notify_infra", "cond": "still_above_85pct"},
{"src": "recheck", "dst": "document"},
{"src": "notify_infra", "dst": "document"}
],
"created_at": 1768471200000,
"namespace": "ops-runbooks",
"importance": 0.9,
"structural_tags": ["infrastructure", "disk-management", "runbook"]
}The three cleanup actions are independent, so they fan out and rejoin. Escalation happens only on the conditional edge. Both paths document.
Manufacturing Standard Operating Procedures
Manufacturing SOPs are full of quarantine branches — a quality check either passes or it does not, and the two outcomes diverge sharply:
{
"type": "workflow",
"trigger": "batch quality check required for production line B",
"nodes": ["pause_line", "sample", "measure_cmm", "measure_roughness", "compare_spec", "quarantine", "approve", "resume_line"],
"edges": [
{"src": "pause_line", "dst": "sample"},
{"src": "sample", "dst": "measure_cmm"},
{"src": "sample", "dst": "measure_roughness"},
{"src": "measure_cmm", "dst": "compare_spec"},
{"src": "measure_roughness", "dst": "compare_spec"},
{"src": "compare_spec", "dst": "quarantine", "cond": "out_of_tolerance"},
{"src": "compare_spec", "dst": "approve", "cond": "within_tolerance"},
{"src": "approve", "dst": "resume_line"}
],
"created_at": 1768471200000,
"namespace": "manufacturing-sops",
"structural_tags": ["quality-control", "line-B", "batch-inspection"]
}Note that quarantine is a terminal node — it has no outgoing edges, so the line does not resume. That is expressed purely by topology.
Automated Trading Strategies
Trading strategies are procedures triggered by market conditions, and their pre-trade checks are naturally concurrent:
{
"type": "workflow",
"trigger": "RSI crosses below 30 on 4-hour timeframe",
"nodes": ["confirm_daily_rsi", "check_ma_200", "check_volume", "size_position", "place_limit_buy", "set_stop_loss", "set_take_profit", "log_setup", "stand_down"],
"edges": [
{"src": "confirm_daily_rsi", "dst": "check_ma_200"},
{"src": "confirm_daily_rsi", "dst": "check_volume"},
{"src": "check_ma_200", "dst": "size_position", "cond": "all_filters_pass"},
{"src": "check_volume", "dst": "size_position", "cond": "all_filters_pass"},
{"src": "check_ma_200", "dst": "stand_down", "cond": "filter_failed"},
{"src": "check_volume", "dst": "stand_down", "cond": "filter_failed"},
{"src": "size_position", "dst": "place_limit_buy"},
{"src": "place_limit_buy", "dst": "set_stop_loss"},
{"src": "set_stop_loss", "dst": "set_take_profit"},
{"src": "set_take_profit", "dst": "log_setup"}
],
"created_at": 1768471200000,
"namespace": "trading-strategies",
"importance": 0.9,
"structural_tags": ["mean-reversion", "equities", "systematic"]
}Customer Escalation Procedures
Support escalation is where bounded cycles earn their place. A "provide customer update every 30 minutes" step is a genuine loop — it repeats until the incident resolves, and it needs a bound so an agent cannot spin forever:
{
"type": "workflow",
"trigger": "enterprise customer reports data loss incident",
"nodes": ["page_oncall", "open_p1_ticket", "acknowledge_customer", "assign_commander", "investigate", "update_customer", "schedule_review", "deliver_report"],
"edges": [
{"src": "page_oncall", "dst": "open_p1_ticket"},
{"src": "page_oncall", "dst": "acknowledge_customer"},
{"src": "open_p1_ticket", "dst": "assign_commander"},
{"src": "acknowledge_customer", "dst": "assign_commander"},
{"src": "assign_commander", "dst": "investigate"},
{"src": "investigate", "dst": "update_customer"},
{"src": "update_customer", "dst": "investigate", "cond": "unresolved", "max_cycles": 48},
{"src": "update_customer", "dst": "schedule_review", "cond": "resolved"},
{"src": "schedule_review", "dst": "deliver_report"}
],
"created_at": 1768471200000,
"namespace": "customer-support",
"importance": 0.95,
"structural_tags": ["escalation", "p1", "enterprise", "data-loss"]
}The back-edge from update_customer to investigate carries max_cycles: 48 — 24 hours of half-hourly updates. Without that bound, a conforming implementation should reject the grain.
Serialization Details
When a Workflow grain is serialized following the canonical algorithm (Section 4.9):
- Validate required fields:
typemust be"workflow",nodesmust be a non-empty array of unique strings,created_atmust be present. Validate that everysrc,dst,bindingskey, andretrieskey references a declared node, and that no cycle is unbounded. - Compact field names via the field map:
typebecomest,created_atbecomesca,namespacebecomesns,importancebecomesim. Among the Workflow-specific fields, onlybindingsshortens — tobind.trigger,nodes,edges, andretrieskeep their full names (Section 6.4). Inside each edge map,src,dst, andcondkeep their names;max_cyclescompacts tomxc. - Preserve array order: The
nodesarray maintains insertion order (Section 4.6). This is critical — the entry point is defined as the first element. - NFC-normalize all strings (Section 4.4), including every node ID, condition string, and the trigger.
- Omit null values (Section 4.5).
- Sort map keys lexicographically (Section 4.1) — including the keys inside each edge map and inside
bindandretries. - Encode as MessagePack.
- Prepend the 9-byte fixed header with type byte
0x04. - Hash with SHA-256.
Workflows and the Success/Failure Feedback Loop
While Workflows do not have a confidence field, they participate in a feedback loop through two core fields available on all grain types (Section 6.1):
success_count(int, non-negative) — number of times this workflow was executed successfullyfailure_count(int, non-negative) — number of times execution failed
Because grains are immutable, these counts are tracked by creating new Workflow grains that supersede the current one with updated counts. Over time, the ratio provides an empirical reliability measure.
The graph model sharpens this feedback considerably. Because every execution writes Tool grains tagged mg:step_action:<node_id>, failure is attributable to a specific node rather than to the procedure as a whole. A workflow whose failures cluster on one node does not need a rewrite — it needs a retries entry, a better binding, or a conditional bypass around that node.
Sharing Workflows Across Agents
Because Workflows are self-contained grains with standard serialization, they can be shared between agents, teams, and organizations:
- Within a team: Agents in the same namespace can discover and use each other's Workflows.
- Cross-team: The
related_tofield (Section 14.2) can link a Workflow to related Workflows in other namespaces, withrelation_type: "similar"or"elaborates". - Cross-organization: Workflows can be exported as
.mgfiles (Section 11) and imported by other systems. The content address provides integrity verification. - With signing: For high-trust sharing, Workflows can be wrapped in COSE Sign1 envelopes (Section 9) with the author's DID, providing cryptographic proof of authorship.
One caveat travels with the graph model: bindings are content addresses of Tool definition grains, and a receiving store that does not hold those grains cannot resolve tier one. That is not a defect — resolution falls through to the Named and Abstract tiers, so a shared workflow degrades to a readable plan rather than breaking. But an exporter that wants full fidelity should include the bound Tool definitions in the same .mg container.
Design Considerations
Node Granularity
How detailed should each node be? There is no spec-defined rule, but practical guidance:
- Each node should be a single, actionable step
- Node IDs should be understandable in isolation, since they double as labels
- If a node has real internal structure, consider a separate Workflow for the sub-procedure and reference it with
related_to
Model Concurrency Honestly
The temptation is to serialize everything — a straight line is easier to reason about. Resist it where the real procedure branches. A plan that says three checks run in sequence, when they actually run in parallel, will mislead every executor and every auditor who reads it. If steps are independent, give them independent edges.
Bound Every Cycle
If you add a back-edge, add max_cycles or a retries entry in the same commit. A conforming implementation should reject an unbounded cycle, so an unbounded one is not "permissive" — it is a grain that may fail validation on import.
Namespace Organization
Use namespaces to organize Workflows by domain: "ops-runbooks", "deployment", "customer-support", "trading-strategies". This enables efficient namespace-based filtering via the header namespace hash (bytes 3-4) without payload deserialization.
Summary
Workflows encode procedural memory — the knowledge of how to do things. Since OMS v1.4 the model is a directed graph: nodes name the steps, edges connect them, bindings attach them to real tools, and retries bound repetition. Structure is inferred from topology rather than declared, so a fork, a join, a decision point, and a terminal node are all consequences of how the graph is wired — with nothing to contradict.
The real power comes from four characteristics:
-
Expressiveness: Parallel fan-out, AND-joins, conditional branching, and bounded cycles are first-class, so a plan can say what a real procedure actually does instead of flattening it into prose.
-
Learnability: Agents can extract Workflows from observed patterns in Tool and Event grains — and the graph target preserves the concurrency and retry structure a flat list would discard.
-
Versioning: The immutability model and supersession chain provide automatic, auditable version history. Execution records attach by relation, so runs never mutate the plan.
-
Shareability: As standard OMS grains, Workflows can be shared across agents, teams, and organizations with integrity verification via content addressing and optional cryptographic signing.
Whether encoding IT runbooks, manufacturing SOPs, trading strategies, or customer escalation procedures, Workflows turn informal knowledge into structured, verifiable, portable procedural memory. They are the playbooks that agents can follow, share, improve, and trust.