目次

ActQL

AIエージェントのための、SQLベースのデータ&ワークフローエンジン。

SaaS、データベース、ファイルをまたいでデータを読み、結合・加工する。非構造データはLLMで解析し、結果は承認を挟んで安全に書き戻す。これまでワークフローSaaSとグルーコードを組み合わせて実現していた処理を、SQLで1つのプログラムとして書いて、そのまま安定して動かせます。

ActQLを使うと、CRM、ファイル、SaaSのAPI、データウェアハウスといった、つないだシステム全体を1つのデータベースのように扱えます。

90秒でわかるActQL
npm install -g actql

バージョン v0.0-alpha · Apache-2.0

1.ActQLで何ができるか

商談の議事録はGoogle Driveに、商談そのものはSalesforceにある。商談ごとに最新の議事録を読み、フェーズや次のステップが変わったかをLLMに判断させて、更新をSalesforceに書き戻す。これを一本のSQLパイプラインで書けます。基本はSQL。LLMを呼ぶ INFER と、外部システムに書き込む EFFECT が加わります。この例は両方を使っていますが、表を返すだけの問い合わせや、LLMを使わないワークフローも、その手順を省いた同じプログラムです。

deal-review.aql
SELECT o.id AS id, o.StageName, o.NextStep,
       c.content AS notes
FROM salesforce.opportunities AS o
JOIN drive.files AS f ON f.name = o.name
JOIN drive.contents AS c USING (resource, version)
|> INFER `model-task:deal-review.v1`
     INPUT (StageName, NextStep, notes) AS review
|> WHERE review.outcome = 'ok' AND review.value.changed
|> RESULT updates
|> EFFECT UPDATE salesforce.Opportunity
     ID id SET (
       StageName = review.value.stage,
       NextStep = review.value.next_step
     );
  • 複雑な処理も、SQL1つ。SaaSのAPI、DWH、データベースをまたぐ処理が、途中でLLMを呼んでも呼ばなくても、一つのプログラムになります。SaaSのデータも、DWHのデータも、LLMの出力も型の決まった同じ表として扱えるので、普通のSQLで結合・絞り込みでき、食い違いは実行前に見つかります。
  • 運用の基盤は、実行エンジンにお任せ。認証・リトライ・状態管理、途中で落ちたときの再開まで、エンジンが引き受けます。Run(1回の実行)は完了した処理を繰り返さず、結果が不明な書き込みはむやみに再送しません。
  • AIが書き、エンジンが検証し、人が承認する。書き込みは、実際に変わるレコードと値を見て承認します。承認の流れは自分で組めます。件数や対象で分岐して、影響の小さいものはそのまま実行し、一部はルールで承認し、リスクの高いものだけ人に回す、といった振り分けを書けます(後述)。
  • オープンソースで、ローカルですぐ始められる。実行エンジンはApache 2.0のオープンソースです。認証も、リトライも、再開も、書き込み前の検証も、中身を読んで確かめられます。SQLiteやDuckDBと同じように、サーバーを立てずアカウントも作らず、CLIからでもライブラリとしてでも、そのまま使い始められます。

動かし方は3つ。CLIから実行する(自分でも、コーディングエージェントに任せても)、TypeScript・Python SDKであなたのアプリに組み込む、ActQL Cloudでそのまま実行する。

いま使っている道具から、ActQLへ:

SQL・dbt・BI

手元で管理しているモデルを、SaaSのデータと合わせて使う。いまのSQLツールからActQLにつなぐ。

TypeScript・Python・アプリ

自分のアプリからシステムをまたいで問い合わせ、ローカルのConnectorでテストして、機能として出す。

AIエージェント・MCP

同じプログラムを型付きのツールとしてエージェントに渡し、検査・権限・Runの記録を共通にする。

2.はじめる

1CLIで商談レビューの例を動かす

CLIをインストールしてサンプルのプロジェクトを作り、Salesforce、Google Drive、LLMをモックに置き換えて実行します。認証情報は不要です。

shell
$ npm install -g actql
$ actql init --template deal-review-mock deal-review && cd deal-review
$ actql run deal-review.aql --stop-before commit

RunはSalesforceに書き込む前で止まり、これから何を変更するのかをそのまま表示します。

Run run_...
  Status      waiting_checkpoint
  Checkpoint  ckpt_...
  Effect      update  (Salesforce Opportunity)
  Items       2
  Changes
    Acme Corp - Renewal   StageName  Proposal      → Negotiation
                          NextStep   (empty)       → Send revised pricing by Friday
    Globex - Expansion    StageName  Negotiation   → Closed Lost
                          NextStep   Legal review  → Revisit next fiscal year

承認してから、Runの状態を確認します。

shell
$ actql approve '<checkpoint-id>'
$ actql status '<run-id>'

これはコーディングエージェントが使うのと同じ流れです。実行の前には check で検査し、explain で計画を確かめられます。--json を付ければ、エージェントやCIが読み取れる形式で出力されます。エージェントに書き方を覚えさせるにはプログラムを書くを、コマンドの一覧はCLIリファレンスを参照してください。

2自分のアプリに組み込む

同じ商談レビューの例をライブラリとしてアプリの中から動かせます。ワークフローサーバーは要りません。

app.ts
import {readFile} from 'node:fs/promises';
import {connect} from '@actql/node';

const client = await connect({mode: 'local', installation: {directory: '.actql'}, profile: 'mock'});
try {
  const source = await readFile('deal-review.aql', 'utf8');
  const execution = await client.startSource(source, {format: 'aql', stopBefore: 'commit'});
  const state = await execution.wait();
  console.log(state.status);         // 'waiting_checkpoint'
  console.log(state.checkpoint?.id); // approve it: actql approve <checkpoint-id>
} finally {
  await client.close();
}

どちらもCLIの例と同じくCheckpointで止まります。コードから始めたRunも、actql status <run-id> で状態を確認し、actql approve <checkpoint-id> で承認できます。.actql には実行の状態が保存されます。バージョン管理には含めないでください。

3.なぜ、新しいエンジンを作るのか

ActQLは、iPaaS、ETL、ワークフローエンジンの今の使われ方に対する4つの問いから始まりました。

Q1なぜ、データ量や用途によって別々の製品が必要なのか

SaaS間で数件のレコードを同期するならiPaaS。数TBを動かすならETL。DWHのデータをSaaSに戻すならReverse ETL。途中で失敗するかもしれない処理を確実に続けるならワークフローエンジン。でも、根っこではどれも同じことをしています。読む、計算する、書く。それを安定して運用する。1レコードと数TBでは、最適な実行方法は違います。それでも、本当に別々の製品が必要なのでしょうか。

Q2AIがワークフローを書くのに、なぜ人間がまだ手でノードをつないでいるのか

ワークフローのUIは、人間がGUIでノードをつなぐために作られてきました。でも、エージェントがプログラムを書くなら、仕事の現場はもうキャンバスの上にはありません。しかもノードは重ねるほど複雑になります。数個のうちはわかりやすくても、何十ものノードの設定に、APIごとの認証やページングの違いが混ざり込み、全体で何が行われるのかを見通せなくなります。

Q3なぜ、ワークフローをアプリに組み込むのは大仕事なのか

アプリでSQLを使いたいなら、SQLiteやDuckDBを組み込めばいい。ところが、アプリから数個のSaaSを操作したいだけなのに、別のワークフローサーバーやSaaSを運用するか、認証・状態管理・再試行・復旧を自前で作るかの二択になります。

Q4AIが処理を書くなら、誰がそれを確かめるのか

AIを使えば、ワークフローもスクリプトも一瞬で書けます。でも、書かれたものが何を書き換えるのか、失敗したら何が確定して何が不明なのかを、人がすべて読んで確かめることはできません。

エージェントは速く書き、人はゆっくり読む。この差は速く読むことでは埋まりません。処理を、機械が検査・実行・許可の判断までできる形で書くことで埋まります。そうすれば、人が呼ばれるのは、本当に人の判断が必要なときだけになります。

4.ActQLの答え:5つの設計

先の4つの問いに、ActQLは次の設計で順に答えます。5つめは、その先にある拡張です。

1Any scale:データ量が変わっても、同じプログラムのまま

SQLでは「どんなデータが欲しいか」を書くだけで、どう取ってくるかはデータベースが自動で最適化して実行します。ActQLはこの仕組みを、システムをまたぐ計算とアクションに広げます。プログラム(Program)には何をしたいかだけを書き、どこで計算するかの計画(Plan)はエンジンが決めます。

計画の仕組みは一つです。Snowflakeのような DWH も、SalesforceのようなSaaSのAPIも、DuckDBも、自分にできる演算をCapabilityとして宣言しています。エンジンはそれを見て、処理の各部分を実行できる場所に任せます(Pushdown)。Salesforceのように問い合わせAPIが柔軟なら、そのCapabilityを最大限使い、全体で最適な実行計画を組み立てます。SalesforceとSnowflakeをまたぐJOINのように、どのソースにも任せられない処理は、手元のマシンで内蔵のエンジンを使って実行します。入力が大きければ、DuckDBを同梱したパッケージでDuckDBに任せます。JOINのために新しいDWHを用意する必要はなく、大きな計算はPushdownでデータのある場所に任せます。

Salesforceの取引先とSnowflakeの利用データをJOINし、LLMで解約リスクを判定して書き戻すプログラム(クイックスタートの例)なら、actql explain でこんな計画が見えます。JOINをどのエンジンで実行するかは、件数が分かってからRunの中で決まります。

$ actql explain churn-risk.aql

[1] READ  salesforce.accounts
    Site: connector:salesforce
    Pushdown: selected

[2] READ  snowflake.usage_30d
    Site: connector:snowflake
    Pushdown: selected

[3] JOIN  [1] + [2]
    Site: host:local (fixed)
    Engine: deferred
      Candidates: ActQL RelA, DuckDB

[4] INFER  churn-risk.v1
    Site: model provider

[5] WHERE  on risk
    Site: host:local
    Engine: deferred
    Pushdown: not eligible
      Reason: depends on INFER output

[6] EFFECT UPDATE  salesforce.Account
    Site: connector:salesforce
    Checkpoint: conditional

処理をどこに移しても、プログラムの意味は変わらず、権限の範囲を越えて実行されることもありません。

ActQL Cloudを使えば、同じプログラムを、自分でHostを運用せずにマネージド環境で動かせます。手元のマシンに収まらない規模の処理も任せられます。

データが増えれば、実行方法は変わる。書くプログラムは変わらない。

2Cross-system:ノードの代わりに、読めるプログラムで

データの取得、変換、必要ならLLMによる推論、外部への書き込みを、一つのプログラムに上から順に書きます。全体で何が起きるかは、プログラムを読めばわかります。

テキストのプログラムは、エージェントが一番得意な形式でもあります。差分でレビューでき、Gitで履歴を残せ、プルリクエストで変更を確かめられます。キャンバス上のノードでは難しかったことです。

APIごとの認証、ページング、レート制限、書き込みの作法は、Connectorの内側で引き受けます。プログラムに出てくるのは salesforce.opportunities や drive.contents といった名前だけで、APIごとの違いをプログラムの側で意識する必要はありません。使えるConnectorは対応Connectorを参照してください。

3Embeddable:サーバーなしで、アプリに組み込める

TypeScriptやPythonから、ライブラリとして読み込むだけで使えます。同じAPIでリモートのエンジンにも接続できます。コアはJavaScript、WebAssembly、ネイティブで動くので、サーバーからEdgeまで同じエンジンを持ち込めます。

認証、状態管理、再試行、復旧を自前で作る必要はありません。Runはアプリのディレクトリに永続化され、プロセスが落ちても続きから再開できます。認証情報とポリシーは、エンジンを動かす側(Host:あなたのアプリやCLI、サーバー)が持ち、プログラムには書きません。

  • アプリに組み込む:ユーザーが操作したときだけ、システムをまたぐ処理を自分のアプリの中で実行する。専用のワークフロー基盤は要りません。
  • ローカル開発:テスト用Connectorと手元の状態で失敗を再現する。本番のSaaSをデバッガ代わりにする必要はありません。
  • CI:プルリクエストごとに型と入出力の取り決めを検査し、テスト用Connectorで期待どおりの結果になるかを確かめる。
  • 本番へ:同じプログラムのまま、手元から本番のHostへ移す。変わるのは接続先、認証情報、ポリシーだけです。

4AI-native:AIが書き、エンジンが検査し、Hostが決める

AIが書く。

構文はGoogleSQLとそれを自然に拡張したものなので、エージェントはすでに書き慣れています。対応するGoogleSQLの構文は、そのまま使えます。どのエージェントフレームワークで書かれたプログラムも、同じ仕組みで検査・実行されます。

エンジンが検査する。

ActQLは見た目だけSQLに似せたDSLではありません。リレーショナル代数を土台に、グラフ・ベクトル・イベント系列の演算にも型を定義し、データの取得や外部への書き込みも明示的な演算として扱います。そして、あえてチューリング完全にはせず、プログラムの停止性と事前の検査しやすさを選んでいます。だから型、必要な権限、起こりうる変更を実行前に検査でき、入力に依存する条件や実際の認可は実行時に確認します。

Hostが決める。

外部への書き込み(Effect)を実行するかどうかは、すべてHostのポリシーが決めます。そのまま通すか、拒否するか、判断に回すか。判断に回った書き込みは、あなたのコードがプレビューを受け取ります。ルールで自動承認するか、人や承認アプリに振り分けるかは、ユースケースに合わせて決められます。決められるのは「通すか否か」だけで、書き込む内容は変えられません。エージェントが自分に許可を与えることもできません。

承認に回った書き込みは Checkpoint で止まります(はじめるの例)。レビュー担当者が見て承認するのは、これから書き込まれる実際のレコードと値で、エージェントの説明文ではありません。書き込む内容は記録済みの結果から決まるので、承認した書き込み内容がcommitまでの間に変わることはありません。結果が不明な書き込みも、やみくもに再送せず、Connectorの仕組みで確かめてから進めます。

最初は人がすべて確認し、安定したものから無人の実行へ移していく、という段階的な任せ方も、この同じ仕組みのままできます。

5Beyond tables:ベクトル検索やグラフも、同じプログラムで

ベクトル検索、グラフ探索、イベント系列のマッチングも、型の決まったレコードとして結果を返すので、通常のJOINやフィルタ、INFER、EFFECT とそのまま組み合わせられます。たとえば、緊急の問い合わせ(Case)ごとに似たナレッジベース記事を3件探し、それを材料に INFER で返信案を作るならこうです。

draft-reply.aql
SELECT c.id, c.description AS question, c.embedding AS query_vec
FROM salesforce.cases AS c
WHERE c.priority = 'urgent'
|> NEAREST kb.articles USING (query_vec) K 3 AS hit
|> AGGREGATE ARRAY_AGG(hit.body ORDER BY hit.rank) AS refs
     GROUP BY id, question
|> INFER `model-task:draft-reply.v1`
     INPUT (question, refs) AS draft

いわゆるRAGを、検索基盤やグルーコードを別に用意せずに書けます。

テーブルの扱いがGoogleSQLに沿っているのと同じく、グラフ探索にはISO標準のGQLやSQL/PGQに由来するパターン構文を採用しています。顧客・取引先・製品のつながりのような関係グラフや、グラフとして表した業務のオントロジーも、SQLと組み合わせて問い合わせられます。(内部では、リレーション、グラフ、ベクトル、イベント系列を、RelA、SGA、VecA、TEAという4つの代数で一つの体系として扱っています。)

5.対応Connector

以下のConnectorは、いずれも読み取りと書き込みの両方に対応しています。

DB・DWHSnowflake · BigQuery · DuckDB
SaaSSalesforce · HubSpot · Slack · Notion · kintone · GitHub · Tableau
GoogleGoogle Sheets · Google Drive · Gmail · Google Calendar
ストレージ・ファイルAmazon S3 · Google Cloud Storage · ローカルファイル

他のシステムにつなぐConnectorは、Connectorを作るを参照して自作できます。そのガイドを参照するSkillsを使えば、コーディングエージェントにも任せられます。

6.既存ツールとの関係

既存のツールとの関係は、使い分けるもの、組み合わせるもの、計算を任せる先の3つに分かれます。

使い分ける

ツールそのツールが向いている場面ActQLが向いている場面
自前のスクリプトPython、TypeScript一度きりの小さな連携を、すぐに書きたい再試行・復旧・承認・権限の管理まで含めて、続けて運用したい
iPaaSn8n、Zapier少数のSaaSを、GUIでさっとつなぎたい連携が増えても全体を見通したい。エージェントに書かせたい。自分のアプリに組み込みたい。書き込みを承認つきで回したい
Reverse ETLCensus、HightouchDWHで整えたデータを、決まった形でSaaSへ定期的に同期したいSaaSのデータとJOINしたり、LLMで判断したりしてから、承認つきで書き戻したい

組み合わせる

ツール使い方
ワークフローエンジンTemporalTemporalの代わりではない。何日も続く長期のジョブはTemporalが管理し、その中の一手順として、システムをまたぐ読み書きをActQLに任せる
dbtモデル、依存関係、テストはdbtのまま。整えたデータをActQLがSaaSのデータと合わせて、システムをまたぐ問い合わせや書き込みに使う。dbt-actqlを使えば、対応するモデルの実行先をActQLにもできる
エージェントフレームワークLangGraph、Mastraエージェントそのものはフレームワークで作り、エージェントが書いた処理の検査・承認・実行をActQLに任せる。ActQLのプログラムは、エージェントのツールとして呼べる

計算を任せる先

ツール使い方
DWHSnowflake置き換えない。大規模な計算は、PushdownでDWHに任せる
組み込みDBDuckDB、SQLiteアプリにSQLを組み込むのと同じ考え方を、システムをまたぐ処理に広げる。DuckDBは、どのソースにも任せられない処理のPushdown先としても使う

ActQLブログを購読する

リリース情報やブログの記事をメールでお届けします。

プライバシーポリシー