ObjectOS
構築

フローと自動化

宣言的なビジネスロジック — AI に記述してもらうか TypeScript で記述するかにかかわらず、ランタイムはどちらの場合も同じアーティファクトを実行します。

フローと自動化

フローは、サーバーを書くことなくビジネスロジックを表現する方法です。 すべてのフローは、ランタイムが実行する宣言的なメタデータであり、これはオブジェクトやビューと同じです。つまり、フローは os diff、監査ログ、Console のフロービルダー、そして AI Builder のすべてに一度に表示されます。

ほとんどのお客様は、AI に依頼してフローを作成します。

「優先度の高いチケットが 30 分間「new」のままになっていたら、Slack でマネージャーに通知して。」

AI は以下のフローを生成します。このページでは、その構造を読んで編集できるように説明します。

スタックでこの機能を有効にします。

export default defineStack({
  // ...
  requires: ['automation'],
});

3 つのフロータイプ

タイプトリガー元用途
Autolaunchedレコードの変更(挿入/更新/削除)「ユーザー登録時にウェルカムメールを送信する」
ScheduledCron 式または間隔「毎晩 2 時に古いタスクをマークする」
Manualユーザーが Console でボタンをクリック、または API 呼び出し「請求書を承認する」アクション

Autolaunched: レコードの変更に反応する

// src/flows/welcome_email.ts
import { defineFlow } from '@objectstack/spec';

export const welcomeEmail = defineFlow({
  name: 'welcome_email',
  type: 'autolaunched',
  trigger: {
    object: 'sys_user',
    when: 'after_insert',
  },
  steps: [
    {
      type: 'action',
      action: 'send_email',
      inputs: {
        to:      '{!trigger.record.email}',
        subject: 'Welcome to {!org.name}',
        body:    'Hi {!trigger.record.name}, welcome aboard.',
      },
    },
  ],
});

変数の補間: {!trigger.record.<field>}{!org.<field>}{!user.<field>}{!step.<step-name>.output}condition: ブロックでは CEL 式を使用します。

トリガーのタイミング:

when発火
before_insert書き込みトランザクション内、INSERT の前
after_insertコミット後
before_update書き込みトランザクション内、UPDATE の前
after_updateコミット後
before_delete書き込みトランザクション内、DELETE の前
after_deleteコミット後

before_* フローは、書き込まれるレコードを変更できます(フィールドの計算、データの正規化)。after_* フローは非同期で実行され、低速な外部サービスを呼び出すことができます。

Scheduled: 時刻に従って実行する

export const nightlyCleanup = defineFlow({
  name: 'nightly_cleanup',
  type: 'scheduled',
  schedule: { cron: '0 2 * * *', timezone: 'America/New_York' },
  steps: [
    {
      type: 'query',
      query: { object: 'task', filter: 'status:open AND due_lt:now()' },
      output: 'stale',
    },
    {
      type: 'foreach',
      items: '{!step.stale}',
      do: [
        { type: 'update', record: '{!item.id}', fields: { status: 'overdue' } },
      ],
    },
  ],
});

@objectstack/service-job 機能に支えられています。詳しくは Runtime Capabilities を参照してください。

Manual: アクションと承認

export const approveInvoice = defineFlow({
  name: 'approve_invoice',
  type: 'manual',
  inputs: {
    invoice_id: { type: 'lookup', reference: 'invoice', required: true },
    note:       { type: 'textarea' },
  },
  steps: [
    {
      type: 'update',
      record: '{!inputs.invoice_id}',
      fields: { status: 'approved', approved_by: '{!user.id}' },
    },
  ],
});

Console で Invoice ビューのボタンとして表示するか、REST 経由で呼び出します。

curl -X POST https://app.example.com/api/v1/actions/invoice/approve_invoice \
  -H 'Authorization: Bearer <token>' \
  -d '{"inputs": {"invoice_id": "inv_123", "note": "OK"}}'

ステップタイプ

ステップ目的
queryObjectQL でレコードを読み取る
create / update / deleteオブジェクトに書き込む
action組み込みアクションまたはプラグイン登録アクションを呼び出す(メール、Webhook、AI 呼び出し、…)
conditionCEL 式で分岐する
foreachコレクションを反復処理する
parallelサブステップを並行して実行する
wait一定時間 / タイムスタンプまで / 条件が満たされるまで一時停止する
subflow別のフローを呼び出す
approvalユーザーが承認するまでブロックする(@objectstack/plugin-approvals が必要)

条件と分岐

{
  type: 'condition',
  when: 'trigger.record.amount > 10000',
  then: [
    { type: 'action', action: 'send_slack', inputs: { /* ... */ } },
  ],
  else: [
    { type: 'update', record: '{!trigger.record.id}', fields: { status: 'auto_approved' } },
  ],
}

エラー処理

各ステップは以下を受け付けます。

{
  type: 'action',
  action: 'send_email',
  inputs: { /* ... */ },
  retry: { attempts: 3, backoffMs: 1000, multiplier: 2 },
  onError: 'continue' | 'fail' | 'rollback',
}

autolaunched の before_* フローでは、onError: 'fail'(デフォルト)は元の書き込みトランザクションを中止します。after_* フローでは、元の書き込みはすでにコミットされており、失敗したフロー実行はジョブの再試行キューに入ります。

数式と式(CEL)

条件、動的なフィールド値、フィルター式はすべて CEL(Common Expression Language)を受け付けます。これは、安全な式評価のための Google の言語です。

'amount > 10000 && account.tier == "enterprise"'
'duration(now() - created_at) > duration("30d")'
'has(record.notes) && record.notes != ""'

CEL はサンドボックス化されており(副作用なし、I/O なし)、サーバー側で評価され、フロービルダーで監査可能です。

ビジュアルビルダー

Console には、宣言的なメタデータとラウンドトリップするビジュアルフロービルダーが付属しています。エンジニアでない人でもフローを編集でき、手作業で記述する TypeScript と同じ構造にシリアライズされます。

フローのテスト

os test --scenario "welcome email fires on signup"

制限とベストプラクティス

  • before フックは小さく保ちます。 書き込みトランザクションをブロックします。
  • 長時間実行されるステップの代わりに wait を使用します。 スリープするフローはワーカーをブロックしますが、wait until はワーカーをプールに返します。
  • 独立したステップには parallel を使用します。 デフォルトは順次実行です。
  • 冪等性が重要です。 再試行では同じステップが 2 回実行されることがあります。外部の副作用は重複排除する必要があります(フロー実行 ID をキーとして使用します)。
  • 監査が必要なアクション。 権限を変更したりレコードを削除したりするフローは、それ自体を sys_audit_log に記録する必要があります。

次のステップ

  • Webhooks — アウトバウンド通知。多くの場合フローからトリガーされます
  • Emailsend_email アクションのトランスポート
  • AI Service — LLM ステップ用の ai_call アクション
  • API Access — 外部システムから手動フローを呼び出す
  • @objectstack/service-automation — 実行エンジンのソース

On this page