目次
ガイド

ローカルとリモートのHost

プログラムがどこで動き、誰が何をしてよいか。ローカルとリモートのHost、プロジェクトとHostの設定、標準のポリシー。

このページは、ActQLを動かす人のためのものです。Hostが何を管理するのか、プロジェクトでローカルのHostをどう設定するのか、Storeはどこに置かれるのか、接続と認証情報をどう宣言するのか、そして読み取り・LLMの呼び出し・Effectを進めてよいかをポリシーがどう決めるのかを説明します。最後に、リモートのHostとActQL Cloudに触れます。Hostの考え方そのものはアーキテクチャを読んでください。

Hostが管理するもの

プログラムには、認証情報も、ポリシーも、実行環境ごとの上限も含まれません。それらはHostのものです。

  • 接続と認証情報 — どの外部システムに届くか、そこにどう認証するか。
  • ポリシー — 読み取り、LLMの呼び出し、Effectのそれぞれについて、許可するか、拒否するか、判断に回すか。
  • model task — プログラムの INFER が参照する、登録済みの定義。
  • Store — すべてのRunの永続的な記録。観測、LLMの答え、プレビュー、Checkpoint、Result、Effectの台帳。
  • 上限 — プログラム自身の上限に、Hostが上乗せするリソースの上限。

同じプログラムは、必要なものがそろっているHostならどこでも動きます。手元のマシンからサーバーに移すときに変わるのは設定であって、プログラムではありません。

プロジェクトの中のローカルHost

CLIと、NodeやPythonに組み込んだHostは、actql.config.json を読みます。カレントディレクトリから上に向かって探し、パスはそのファイルからの相対パスとして解決します。

{
  "version": "actql-config/0.1",
  "connectors": "./connectors.json",
  "model_tasks": "./model-tasks.json",
  "state_dir": "./.actql"
}
フィールド意味
connectors接続ファイル。どのConnectorが入っていて、どう認証するか。
model_tasksmodel taskの登録ファイル。タスクの定義とLLMのプロバイダー。LLMとINFERを参照。
state_dirStoreの場所。既定は ./.actql。
lock解決済みのConnectorとmodel taskの契約を固定するロックファイル。
mockmockプロファイルのフィクスチャのファイル。

--config、--connectors、--model-tasks などのフラグを付けると、そのコマンドに限って、見つかったファイルの代わりにそちらが使われます。フィールドの一覧は設定にあります。

ファイルを見つけることと、それを信頼することは別です。プロジェクトのファイルは探して見つけるものなので、cloneしたものに何が入っていてもかまいません。供給するのは接続、model task、Storeの場所、フィクスチャだけで、権限を与えるものは含まれません。誰が何をしてよいか、誰が承認できるかはHostの設定です。actql init が作る ~/.config/actql/host.json か、--host-config で指定したファイルに書きます。

{
  "version": "actql-host/0.1",
  "account_config": "./accounts.json",
  "effect_policy": { "decision": "review" },
  "signers": { … }
}
フィールド意味
account_config実行アカウントの設定。接続・リソース・操作ごとに、誰が何をしてよいか。省略可。ポリシーを参照。
run_policy、effect_policyポリシーが判断を委ねたときにどうするか。allow、review(Checkpointで待つ)、deny。
signersCLIからCheckpointを承認できる身元。

プロジェクトのファイルから権限を広げたり承認者を足したりはできないので、リポジトリをcloneしても、何を書き込めるか、誰が承認できるかは変わりません。

Store

Storeは、state_dir で指定したディレクトリです。Runを続けるために必要なものと、何が起きたかを確認するために必要なものがここに入ります。取り込んだ観測、採用したLLMの答え、プレビュー、Checkpoint、Result、そして送ったEffectそれぞれの結果です。Hostが管理する鍵で、保存時に暗号化されます。

  • バージョン管理には入れないでください(.gitignore に .actql/ を追加します)。
  • そのRunとResultが必要なあいだは残しておいてください。status、result、attach はここから読み、再起動後のRunもここから再開します。
  • 保持期間はHostの設定です。Runとその証跡は設定した期間だけ保持され、既定で永久に残るものはありません。

同じ state_dir を指す2つのプロセスは、同じHostの状態を共有します。Storeがleaseとfencingで調停するので、1つのRunを動かすプロセスは常に1つで、古いプロセスが新しい状態を上書きすることはありません。あとでそのディレクトリを開き直せば、そこにあるRunを探して接続し直せます。

接続と認証情報

connectors.json で、各接続に名前を付け、認証の方法を書きます。プログラムは salesforce.accounts のような読み取り元の先頭部分として、この接続名を参照します。

{
  "version": "actql-connectors/0.1",
  "connections": {
    "salesforce": {
      "connector": "salesforce",
      "instance_url": "https://acme.my.salesforce.com",
      "credentials": {"access_token": {"env": "SALESFORCE_ACCESS_TOKEN"}}
    },
    "snowflake": {
      "connector": "snowflake",
      "account": "acme-prod", "warehouse": "ANALYTICS", "database": "PRODUCT",
      "user": "ACTQL",
      "credentials": {"private_key": {"path": "./keys/snowflake.p8"}}
    }
  }
}

秘密情報は参照だけで、ファイルには書きません。認証情報ごとに、環境変数({"env": …})かファイル({"path": …})を指定します。Hostは接続を開くときにそれを読み、ポリシーが受け付けた操作のときだけConnectorに貸し出します。各Connectorに必要なフィールドは、Connectorの各ページにあります。

actql catalog show salesforce は、その接続が公開しているもの、つまり読み取り元とその列、Connectorが宣言する操作とCapabilityを表示します。プログラムを書く前に、何を参照できるかを確認できます。

ポリシー:誰が何をしてよいか

読み取り元を読む、LLMを呼ぶ、データを外に送る、Effectを適用する。保護された境界はどれも、実際に起こる前にポリシーで判断されます。判断は2層です。

1. 実行アカウントの設定

始めるのに、この設定は要りません。account_config がなければ、ローカルのHostは標準のポリシーで動きます。

操作標準のポリシー
純粋な計算(SELECT 1、ローカルの値)動く
設定した接続からの読み取り動く
登録したmodel taskによる INFER動く
あらゆるEffect(UPDATE、INSERT、STORE、COMMAND)effect_policy に委ねる。既定の review はプレビューを作って承認を待つ
エントリが拒否する操作拒否

アカウント設定を書くのは、制限したいとき(チームのポリシー、読み取り専用の接続、特定のプリンシパルだけが呼べるタスク)か、特定のEffectを承認なしで通したいときです。誰にも許可されていない操作を拒否することと、設定が何もないときの体験とは別のものです。前者はあなたが書くルールで、後者はHostの標準のポリシーです。

accounts.json は、プリンシパル × 接続 × リソース × 操作 の組み合わせごとに、次の3つのどれかに振り分けます。

結果意味
allow進める。Checkpointも、判断のコールバックもない。
deny送らない。何によっても覆らない。
delegateHostの委譲先(次の節)に判断を任せる。

操作は read、infer、write、effect です。読み取りは読み取り元の接続に対する操作で、LLMの呼び出しはLLMプロバイダーの接続(下の例では openai)に対する操作です。レコードが来た接続に対する操作ではありません。セレクターは {"all": true}(現在と将来のすべて)か {"any_of": [...]}(明示的な一覧)です。設定を書いた場合、どのエントリにも一致しない組み合わせは拒否され、結果の異なるエントリ同士が重なる場合は設定エラーになります。優先順位を考える必要はありません。

{
  "version": "actql-execution-account-config/0.1",
  "account_id": "acme-local",
  "entries": [
    { "entry_id": "reads", "outcome": "allow",
      "principal": { "all": true }, "connection": { "any_of": ["salesforce", "snowflake"] },
      "resource": { "all": true }, "operation": { "any_of": ["read"] } },
    { "entry_id": "model-calls", "outcome": "allow",
      "principal": { "all": true }, "connection": { "any_of": ["openai"] },
      "resource": { "any_of": ["model-task:churn-risk.v1"] }, "operation": { "any_of": ["infer"] } },
    { "entry_id": "salesforce-writes", "outcome": "delegate",
      "principal": { "all": true }, "connection": { "any_of": ["salesforce"] },
      "resource": { "all": true }, "operation": { "any_of": ["effect"] } }
  ]
}

この設定では、両方の接続の読み取りと、openai を通した解約リスクのタスクの呼び出しはそのまま通り、Salesforceへのすべての Effect は委譲先に回されます。それ以外、たとえば3つ目の接続からの読み取り、別のタスク、SnowflakeへのEffectは拒否されます。

2. 判断の委譲先

delegateされた判断は、運用者が設定したものに届きます。ルール、承認用のアプリ、人、またはその組み合わせです。ローカルのHostでいちばん簡単な委譲先は、設定そのものです。

"effect_policy": { "decision": "review" }

allow はその場で許可し、review は誰かが承認か拒否をするまでCheckpointで待ち、deny はその場で拒否します。run_policy は、Run全体に関する判断について同じことをします。どちらも delegate された判断にだけ効き、アカウント設定の deny を覆すことはありません。

委譲先を自分のコードにすることもできます。組み込みのHostは、connect() の decide オプションに判断の対象そのもの(Effectなら、何が変わるかのプレビュー)を渡して呼び出し、コードは permit、reject、defer のどれかを返します。典型的なのは、規模による振り分けです。

const client = await connect({
  mode: 'local', installation: {directory: '.actql'},
  decide: async (decision) => {
    if (decision.kind !== 'effect_set') return 'permit';          // 読み取りとLLMの呼び出しは通す
    if (decision.preview.items.length <= 100) return 'permit';    // 小さな更新はルールで承認
    return 'defer';                                               // 大きなものは人を待つ
  },
});

委譲先が何であれ、できるのは判断だけです。書き込む内容を変えることはできません。委譲先が答えなかったり失敗したりすれば、何も送られません。deferされた判断が作るCheckpointについては、Effectと承認を参照してください。

承認者(signers)

CLIからCheckpointを承認すると、誰が承認したかが記録されます。signers には、ローカルのHostが受け付ける身元と、それぞれが解決できるCheckpointの種類を書きます。

"signers": {
  "ops-approver": {
    "principal": "ops", "key_id": "ops-2026",
    "private_key": "./keys/ops.pem", "public_key": "./keys/ops.pub.pem",
    "checkpoint_kinds": ["effect_set"]
  }
}

actql approve ckpt_… --signer ops-approver と実行すると、そのCheckpointに結び付いた、認証済みの判断結果が作られます。

承認者を設定していないローカルのHostは、actql init がStoreに生成したローカルの署名鍵を使います。承認は署名され、Checkpointに結び付けられますが、この鍵が示すのはマシンのユーザーであって、本人確認された人ではありません。本番では、Hostが判断を検証できる承認者を設定してください。

mockプロファイル

--profile mock(CLI)または profile: 'mock'(SDK)を指定すると、プログラムはmockのConnectorとmockのLLMに対して動きます。読み取りは設定の mock.data のファイルにあるレコードを返し、LLMは mock.answers の答えを返します。Effectは本物と同じCheckpointを経て、mockのレコードにだけ適用されます。ポリシーは、本物の接続と同じ標準のポリシーです。それ以外、つまり検査、計画、ポリシー、Store、Checkpoint、再開はすべて本物のHostです。認証情報が要らないので、プログラムを試す、テストを書く、失敗を再現する、といった用途にちょうどよい場所です。

リモートのHost

リモートのHostは、HTTPSでプログラムを受け付けます。アプリは同じSDKを使い、ディレクトリの代わりに接続先を指定します。

const client = await connect({mode: 'remote', endpoint: 'actql://host.acme.internal', token: process.env.ACTQL_TOKEN});

endpoint には、actql:// の接続文字列か、Hostの https:// のURLを渡します。接続、認証情報、ポリシー、Storeはサーバー側にあり、呼び出し側が持つのはトークンだけです。そこで作られたCheckpointは、同じSDKの呼び出しで承認します。プログラムはどちらの場合も同じファイルです。

ActQL Cloudは、マネージドなリモートのHostです。自分で運用するものはなく、手元のマシンに収まらない処理も任せられます。同じCoreが動くので、ローカルで動くプログラムはそのまま動きます。

次に読む

  • Effectと承認:Checkpointに何が表示され、どう解決されるか
  • LLMとINFER:model taskとプロバイダーの登録
  • 設定:設定ファイルのすべてのフィールド

Source: actql/actql/docs/guides/hosts.md at d904416674e4 · Edit on GitHub