Skip to main content

Operations

Operations are named, structured interfaces that documents expose to the outside world. They define specific actions that can be performed on a document, complete with formal request definitions.

The Role of Operations in Blue

Blue documents interact with the world through channels, processing events that arrive through these pathways. Operations build on this foundation by creating well-defined action endpoints within a document.

When to use operations:

  • To create clearly named actions that express intent (e.g., approvePayment, scheduleLesson)
  • To enforce specific input structures and validation rules
  • To organize document capabilities into logical functional units
  • To enable discoverability of available actions

Operations provide an organizational layer that helps structure interactions with a document. They create a clear API for document manipulation while working through the same underlying channel mechanisms that power all Blue document interactions.

Defining Operations

Operations are defined using the Operation contract:

increment:
type: Operation
request:
description: Represents a value by which counter will be incremented
type: Integer

This definition specifies:

  1. The operation name (increment)
  2. The expected input structure (request)
  3. A description for the request

Implementing Operations

Once defined, operations need an implementation. The most common approach is using a Sequential Workflow Operation:

incrementImpl:
type: Sequential Workflow Operation
operation: increment
steps:
- type: Update Document
changeset:
- op: replace
path: /counter
val: ${event.message.request + document('/counter')}

This implementation:

  1. Links to the increment operation definition
  2. Defines processing steps that execute when the operation is called

The operation's implementation can access:

  • The request payload via event.message
  • Timeline metadata (actor, timestamp, etc.) via event
  • The current document state via document()
  • Any other contextual information needed

Invoking Operations

Operations are invoked by posting a Timeline Entry whose message is an Operation Request to the document's channel:

type: Timeline Entry
timeline:
type: MyOS Timeline # Or another Timeline Provider
account: alice@example.com
message:
type: Operation Request
operation: increment # Name of the operation to call
request: 5 # The increment value
document:
blueId: 7UEBwTmRMfQ92rGt4vHkzPa8Ypd5KJsLNcA3FV6xDqbn # Target document ID
allowNewerVersion: true # Accept if document has changed
actor:
type: Principal Actor
name: Alice

Request Formats

The request field can contain:

  1. Simple values for primitive types:

    request: 5  # Integer
  2. Structured objects for complex types:

    request:
    a: 12
    b: xyz

The request structure must match what's defined in the operation contract. If it doesn't match, the operation won't execute and will return an error.

The allowNewerVersion Flag

The allowNewerVersion flag addresses an important concern: what happens if the document changes between when you retrieve it and when you send your operation?

  • true: Process the operation on the latest version, even if it changed
  • false: Only process if the document still has the same BlueId as specified

This gives callers control over concurrent modifications:

  • Use true when the operation should work regardless of other changes
  • Use false when the operation depends on the document being in a specific state

Complete Counter Example

Let's bring everything together with our simple counter example:

name: Simple Counter
counter: 0
contracts:
ownerChannel:
type: Timeline Channel

# Defines the increment operation interface
increment:
type: Operation
request:
description: Represents a value by which counter will be incremented
type: Integer

# Implements the increment operation
incrementImpl:
type: Sequential Workflow Operation
operation: increment
steps:
- type: Update Document
changeset:
- op: replace
path: /counter
val: ${event.message.request + document('/counter')}

When a client wants to increment the counter:

  1. It posts a Timeline Entry containing an Operation Request to the document's timeline:

    type: Timeline Entry
    timeline:
    type: MyOS Timeline
    account: alice@example.com
    message:
    type: Operation Request
    operation: increment
    request: 5
    document:
    blueId: 7UEBwTmRMfQ92rGt4vHkzPa8Ypd5KJsLNcA3FV6xDqbn
    allowNewerVersion: true
    actor:
    type: Principal Actor
    name: Alice
  2. Any compliant document processor:

    • Receives the Timeline Entry through the ownerChannel
    • Extracts the Operation Request from event.message
    • Identifies the increment operation and its implementation
    • Executes the Update Document step, adding 5 to the counter
  3. The counter is now incremented by 5

Operations in MyOS

You can run the example above in MyOS.

Natural language operations