Start here
Blue is designed so you can enter at different levels and still work with the same model. Three paths: MyOS + Blink, the JavaScript SDK, and raw Blue. Different depths — one structure.
The easiest entry point. Describe the interaction you want in natural language.
"Create a shop for my restaurant"
"Create a payment mandate for my OpenClaw"
"Set up a delivery agreement with a courier"
"Create an order and connect a payment"
Blink turns that into Blue-backed blocks in MyOS. This is the right path if you want speed, zero setup, a visual or conversational interface, and working examples quickly.
If you want programmatic control but still want ergonomic APIs, use the SDK. The SDK path is right when you want backend integration, automation, tests, type safety, and your own runtime around Blue blocks.
Install the published packages:
npm install @blue-labs/language @blue-labs/document-processor @blue-repository/types
Run the verified Counter document:
import { Blue } from "@blue-labs/language";
import {
DocumentProcessor,
ContractProcessorRegistryBuilder,
createDefaultMergingProcessor,
} from "@blue-labs/document-processor";
import { repository } from "@blue-repository/types";
const blue = new Blue({
repositories: [repository],
mergingProcessor: createDefaultMergingProcessor(),
});
const registry = ContractProcessorRegistryBuilder.create()
.registerDefaults()
.build();
const processor = new DocumentProcessor({ blue, registry });
const document = blue.yamlToNode(`
name: Demo Counter
counter: 0
contracts:
ownerChannel:
type: Conversation/Timeline Channel
timelineId: owner-1
increment:
type: Conversation/Operation
channel: ownerChannel
request:
type: Integer
incrementHandler:
type: Conversation/Sequential Workflow Operation
operation: increment
steps:
- name: ApplyIncrement
type: Conversation/Update Document
changeset:
- op: replace
path: /counter
val: ${event.message.request + document('/counter')}
`);
const init = await processor.initializeDocument(document);
const event = blue.jsonValueToNode({
type: "Conversation/Timeline Entry",
timeline: { timelineId: "owner-1" },
message: {
type: "Conversation/Operation Request",
operation: "increment",
request: 1,
},
});
const result = await processor.processDocument(init.document, event);
// result.document is the next state, result.totalGas is the gas consumed,
// result.triggeredEvents are any side-effect events emitted by the workflow.The example APIs above are real and stable enough for documentation. Specific helpers around higher-level wrappers (MyOS clients, hosted timelines) may evolve as the SDK grows.
If you want full control, you can author Blue directly. This is the right path when you want exact structure, custom documents, protocol-level understanding, and no abstraction between you and the language.
name: Demo Counter
counter: 0
contracts:
ownerChannel:
type: Conversation/Timeline Channel
timelineId: owner-1
increment:
type: Conversation/Operation
channel: ownerChannel
request:
type: Integer
incrementHandler:
type: Conversation/Sequential Workflow Operation
operation: increment
steps:
- name: ApplyIncrement
type: Conversation/Update Document
changeset:
- op: replace
path: /counter
val: ${event.message.request + document('/counter')}The same document can be expressed via Blink, the SDK, or raw YAML. The protocol-level shape is identical.
| Path | What you write | What lands |
|---|---|---|
| MyOS + Blink | "Create a counter that an owner can increment." | The same document, generated and hosted in your MyOS world. |
| JavaScript SDK | blue.yamlToNode('...counter yaml...') + processor.initializeDocument(...) | The same document, parsed and processed by your own code. |
| Raw Blue | The YAML on the left. | Exactly the same document, by hand. |
This is one of the most important design goals of Blue: different entry points, one model.
If you are new:
If you are already technical: