.do

Patterns

Common patterns with @dotdo/types

Function Spectrum

Functions progress through capability tiers, from simple code execution to autonomous agents:

import type {
  CodeFunction,
  GenerativeFunction,
  AgenticFunction,
  HumanFunction
} from '@dotdo/types'

// Tier 1: Code - Pure TypeScript execution
const add: CodeFunction<number, { a: number; b: number }> = {
  $type: 'CodeFunction',
  name: 'add',
  handler: ({ a, b }) => a + b,
}

// Tier 2: Generative - LLM-powered generation
const summarize: GenerativeFunction<string, { text: string }> = {
  $type: 'GenerativeFunction',
  name: 'summarize',
  model: 'claude-3-5-sonnet',
  prompt: 'Summarize the following text: {{text}}',
}

// Tier 3: Agentic - Multi-step reasoning with tools
const research: AgenticFunction<Report, { topic: string }> = {
  $type: 'AgenticFunction',
  name: 'research',
  tools: ['web-search', 'read-page', 'summarize'],
  maxSteps: 10,
}

// Tier 4: Human - Requires human approval
const approve: HumanFunction<boolean, { request: ApprovalRequest }> = {
  $type: 'HumanFunction',
  name: 'approve-expense',
  assignTo: 'manager',
  timeout: '7d',
}

Promise Pipelining

Chain RPC calls without awaiting intermediate results. The platform batches them into a single round-trip:

import type { RpcPromise } from '@dotdo/types'

// CORRECT - single round trip to the server
const repos = await $.auth.verify(token).github.repos.list()

// The above is equivalent to but faster than:
const user = await $.auth.verify(token)  // round trip 1
const github = await user.github         // round trip 2
const repos = await github.repos.list()  // round trip 3

// Complex pipelines work too
const avatar = await api.users
  .get('123')
  .profile
  .avatar
  .resize({ width: 100, height: 100 })

Semantic Modeling

Build domain models from the six semantic primitives:

import type { Thing, Noun, Verb, Event, Action, Domain } from '@dotdo/types'

// Define a domain
const Commerce: Domain = {
  $type: 'Domain',
  $id: 'https://example.com.ai/domains/commerce',
  name: 'Commerce',
  description: 'E-commerce domain model',
}

// Define entities (Nouns)
const Customer: Noun = {
  $type: 'Noun',
  $id: 'https://example.com.ai/nouns/Customer',
  name: 'Customer',
  domain: 'https://example.com.ai/domains/commerce',
  properties: {
    email: { type: 'string', required: true },
    name: { type: 'string' },
  }
}

const Product: Noun = {
  $type: 'Noun',
  $id: 'https://example.com.ai/nouns/Product',
  name: 'Product',
  domain: 'https://example.com.ai/domains/commerce',
  properties: {
    sku: { type: 'string', required: true },
    price: { type: 'number', required: true },
  }
}

// Define operations (Verbs)
const Purchase: Verb = {
  $type: 'Verb',
  $id: 'https://example.com.ai/verbs/Purchase',
  name: 'Purchase',
  domain: 'https://example.com.ai/domains/commerce',
  subject: 'Customer',
  object: 'Product',
}

// Define state changes (Events)
const OrderPlaced: Event = {
  $type: 'Event',
  $id: 'https://example.com.ai/events/order.placed',
  name: 'Order Placed',
  domain: 'https://example.com.ai/domains/commerce',
  data: {
    orderId: { type: 'string' },
    customerId: { type: 'string' },
    total: { type: 'number' },
  }
}

Workflow Composition

Build complex workflows from simple steps:

import type { Workflow, WorkflowStep } from '@dotdo/types'

const orderWorkflow: Workflow = {
  $type: 'Workflow',
  name: 'process-order',
  version: '1.0.0',

  steps: [
    // Sequential steps
    { name: 'validate', type: 'function', function: 'validateOrder' },
    { name: 'charge', type: 'function', function: 'chargePayment' },

    // Parallel fan-out
    {
      name: 'notify',
      type: 'parallel',
      branches: [
        [{ name: 'email', type: 'function', function: 'sendEmail' }],
        [{ name: 'sms', type: 'function', function: 'sendSMS' }],
      ],
    },

    // Conditional branching
    {
      name: 'shipping',
      type: 'condition',
      condition: '$.steps.validate.output.expedited',
      then: [{ name: 'express', type: 'function', function: 'shipExpress' }],
      else: [{ name: 'standard', type: 'function', function: 'shipStandard' }],
    },
  ],

  triggers: [{ type: 'event', event: 'order.placed' }],
}

Type Discriminators

All types include a $type discriminator for runtime type checking:

import type { BaseEvent, Workflow, Agent } from '@dotdo/types'

function handleMessage(msg: BaseEvent | Workflow | Agent) {
  switch (msg.$type) {
    case 'Event':
      console.log('Event:', msg.type, msg.data)
      break
    case 'Workflow':
      console.log('Workflow:', msg.name, msg.steps.length, 'steps')
      break
    case 'Agent':
      console.log('Agent:', msg.name, 'with', msg.tools?.length, 'tools')
      break
  }
}

Event-Driven Patterns

Use events for loose coupling between components:

import type { EventEmitter, EventBus, BaseEvent } from '@dotdo/types'

// Type-safe event emitter
interface OrderEvents {
  'order.placed': { orderId: string; total: number }
  'order.shipped': { orderId: string; trackingId: string }
  'order.delivered': { orderId: string; signature: string }
}

const orders: EventEmitter<OrderEvents> = getEmitter()

// Subscribe with full type safety
orders.on('order.placed', async ({ orderId, total }) => {
  await processOrder(orderId, total)
})

// Publish events
await orders.emit('order.placed', { orderId: 'ord_123', total: 99.99 })

Agent Patterns

Configure agents with tools and policies:

import type { Agent, AgentConfig, AgentTool } from '@dotdo/types'

const researchAgent: Agent = {
  $type: 'Agent',
  name: 'research-assistant',
  description: 'Researches topics and creates reports',

  config: {
    model: 'claude-3-5-sonnet',
    temperature: 0.7,
    maxTokens: 4096,
  },

  tools: [
    { name: 'web-search', description: 'Search the web' },
    { name: 'read-page', description: 'Read a web page' },
    { name: 'write-file', description: 'Write to a file' },
  ],

  policy: {
    maxSteps: 20,
    maxCost: 1.00,
    allowedDomains: ['*.wikipedia.org', '*.arxiv.org'],
  },
}
Edit on GitHub

On this page