PicoClawの現行設定方針メモ

PicoClawの現行設定方針メモ

PicoClaw は設定項目がかなり多いが、現行の方針としては ~/.picoclaw/config.jsonmodel_list 中心で組み立て、必要なチャネルと機能だけを有効化するのが分かりやすい。

この記事は過去の互換設定はいったん脇に置き、今から設定するならどう書くかに絞っている。

まず押さえる方針

  • モデル定義は model_list を使う
  • agents.defaults.model_name で既定モデルを決める
  • チャネルは使うものだけ enabled: true にする
  • allow_from は空にせず、可能なら必ず制限する
  • Web 検索やスキル、MCP などの補助機能はデフォルトを尊重し、必要になってから増やす
  • MCP は npm / node / npx 経由の実装が多いため、可能なら自前の小さい実装、checksum 固定済み binary、lockfile 付き npm install の順で検討する
  • 公開用の設定例にはトークン、ユーザー ID、社内 URL、内部ホスト名を書かない

現行での最小構成

最初はこれくらいで十分だと思う。

{
  "agents": {
    "defaults": {
      "workspace": "~/.picoclaw/workspace",
      "restrict_to_workspace": true,
      "model_name": "gpt-5.4"
    }
  },
  "model_list": [
    {
      "model_name": "gpt-5.4",
      "model": "openai/gpt-5.4",
      "api_key": "sk-your-openai-key",
      "api_base": "https://api.openai.com/v1"
    }
  ],
  "channel_list": {},
  "tools": {},
  "gateway": {
    "host": "127.0.0.1",
    "port": 18790
  }
}

ポイントは、PicoClaw は未指定項目をかなりデフォルトで補完してくれることだ。最初から巨大な config.example.json を全部埋める必要はない。

model_list を中心に考える

現行では providers より model_list を主に使う前提で考えた方がよい。

{
  "model_list": [
    {
      "model_name": "gpt-5.4",
      "model": "openai/gpt-5.4",
      "api_key": "sk-your-openai-key",
      "api_base": "https://api.openai.com/v1"
    },
    {
      "model_name": "claude-sonnet-4.6",
      "model": "anthropic/claude-sonnet-4.6",
      "api_key": "sk-ant-your-key",
      "api_base": "https://api.anthropic.com/v1",
      "thinking_level": "high"
    }
  ],
  "agents": {
    "defaults": {
      "model_name": "gpt-5.4"
    }
  }
}

modelprovider/model-id 形式で書く。たとえば以下のような形になる。

  • openai/gpt-5.4
  • anthropic/claude-sonnet-4.6
  • deepseek/deepseek-chat
  • ollama/llama3
  • codex-cli/gpt-5.3-codex

model_name は人間が使う別名なので、短く分かりやすい名前にしておくと扱いやすい。

agents.defaults は最小限でよい

agents.defaults で最初に気にするのはほぼ次の 3 つだけでよい。

  • workspace
  • restrict_to_workspace
  • model_name

必要になったら、以下を追加する。

  • max_tokens
  • max_tool_iterations
  • summarize_message_threshold
  • summarize_token_percent
  • allow_read_outside_workspace
  • routing

特に restrict_to_workspace: true はそのまま維持した方が安全だと思う。最初から外を読めるように広げない方が事故が少ない。

チャネル設定は「有効化」と「アクセス制限」をセットで考える

チャネルは Telegram、Slack、Discord など複数あるが、方針は同じ。

{
  "channel_list": {
    "telegram": {
      "enabled": true,
      "type": "telegram",
      "token": "YOUR_TELEGRAM_BOT_TOKEN",
      "allow_from": [
        "123456789"
      ]
    }
  }
}

重要なのは allow_from の扱いで、空配列は「誰でも許可」と考えた方がよい。テスト用途でも、公開チャネルに接続するなら最初から制限を入れておく方が安全だ。

allow_from とは何か

allow_from は、そのチャネルでどの送信者からのメッセージを受け付けるかを絞るための許可リスト。

考え方は単純で、次のように使う。

  • allow_from: [] なら全ユーザー許可
  • allow_from に値を入れると、その ID の送信者だけ許可

Bot を自分専用または特定メンバー専用で使いたいなら、基本的には必ず設定した方がよさそう。

Telegram での例

{
  "channel_list": {
    "telegram": {
      "enabled": true,
      "type": "telegram",
      "token": "YOUR_TELEGRAM_BOT_TOKEN",
      "allow_from": [
        "123456789"
      ]
    }
  }
}

Slack での例

{
  "channel_list": {
    "slack": {
      "enabled": true,
      "type": "slack",
      "allow_from": [
        "U0123456789"
      ],
      "reasoning_channel_id": "",
      "settings": {
        "bot_token": "xoxb-YOUR-BOT-TOKEN",
        "app_token": "xapp-YOUR-APP-TOKEN"
      }
    }
  }
}

Slack は Socket Mode 前提のため、少なくとも bot_tokenapp_token の両方が必要になる。 PicoClaw 0.2.8 では Slack token を channel_list.slack 直下ではなく channel_list.slack.settings 配下に置く。直下に置くと unknown field(s): channel_list.slack.app_token, channel_list.slack.bot_token で gateway が起動に失敗する。

公開用サンプルでは次を守るのが無難だ。

  • 実際のトークンは書かない
  • 実際のユーザー ID は書かない
  • allow_from は空にしたサンプルより、制限ありのサンプルを載せる

MCP を増やす時のセキュリティ方針

PicoClaw に MCP を足すと、Slack からの会話が外部 command に届く。MCP server の process 環境には Slack token、App token、kubeconfig、Trello token などを渡しがちなので、MCP の依存 package は通常の CLI より強めに疑った方がよい。

現行の自宅検証環境では、Ubuntu Desktop 向けに次の方針にしている。

  • fetch / search / systemd-status / sqlite-state / git-status / trello は自前 Python MCP とし、npm / node / npx を使わない
  • k8s-status は Go binary を version と sha256 checksum 固定で導入する
  • sqlite-state は read-only SQL に限定し、DB file は 0600、state directory は 0700 にする
  • systemd-status は read-only の systemctl show と短い journal 参照に限定する
  • git-status は許可した repository root 配下だけを読む
  • trello は Trello REST API の GET だけを呼ぶ。PicoClaw 用の read-only token は PICOCLAW_TRELLO_API_KEY / PICOCLAW_TRELLO_TOKEN から Ansible に渡し、config.json に直書きせず、MCP server の env_file0600 の専用ファイルから読む

npm 系 MCP を使う場合は、最低でも次を確認する。

  • npx -y package を常用しない。固定 version を専用 directory に入れ、package-lock.json を残す
  • 可能なら npm ci --ignore-scripts で lifecycle script を無効化する
  • npm audit --audit-level=moderate で既知脆弱性を確認する
  • npm audit signatures で registry signature を確認する
  • provenance がある package は検証する。ただし provenance は build 元を追いやすくする仕組みで、悪意ある code が無い保証ではない
  • MCP process に渡す環境変数を絞り、不要な token を共有しない

確認の入口としては、PicoClaw 側の config に node / npm / npx command が混ざっていないかを見る。

python3 - <<'PY'
import json
config = json.load(open('/home/kaoru/.picoclaw/config.json'))
servers = config.get('tools', {}).get('mcp', {}).get('servers', {})
for name, server in sorted(servers.items()):
    command = server.get('command')
    args = server.get('args') or []
    uses_node = command in {'node', 'npm', 'npx'} or any(str(a).endswith(('/node', '/npm', '/npx')) for a in [command])
    print(f'{name}: command={command} args={args} uses_node_npm_npx={uses_node}')
PY

Slack の自分の ID を確認する方法

Slack の allow_from に入れる値は、通常は自分の Slack User ID。U で始まる値になる。

Slack アプリ上で確認するなら、次の流れが簡単だった。

  1. 自分のプロフィールを開く
  2. 三点メニューを開く
  3. メンバーIDをコピー のような項目を選ぶ

取得できる値は U0123456789 のような形式になる。

Slack 専用 Bot を新しく作る手順

既存の Bot を使い回すより、PicoClaw 専用の Slack App を 1 つ新規で作る方が権限管理もしやすい。

大まかな流れは次のとおり。

  1. Slack App を新規作成する
  2. Socket Mode を有効にする
  3. App-Level Token を作成する
  4. Bot Token Scopes を追加する
  5. Event Subscriptions を設定する
  6. App Home の Messages タブを有効にする
  7. ワークスペースへインストールする
  8. bot_tokenapp_token~/.picoclaw/config.jsonchannel_list.slack.settings に入れる

1. Slack App を新規作成する

  • Slack API の app 管理画面へ行く
  • Create New App を選ぶ
  • From scratch を選ぶ
  • App 名を決める
  • 開発用または利用対象の workspace を選ぶ

PicoClaw 専用なら、用途が分かる名前にしておくと後で見分けやすい。

2. Socket Mode を有効にする

PicoClaw の Slack 実装は Socket Mode 前提なので、ここは必須。

  • App 設定の Socket Mode を開く
  • Enable Socket Mode を ON にする

3. App-Level Token を作成する

Socket Mode 用の xapp-... トークンを作る。

  • App 設定の Basic Information を開く
  • App-Level Tokens で新しい token を作る
  • scope は connections:write を付ける

これが config.jsonchannel_list.slack.settings.app_token になる。

4. Bot Token Scopes を追加する

PicoClaw 用として、まずは次の権限を追加すればよい。

必須スコープ

  • app_mentions:read
    • 効果: チャンネル内で Bot へのメンションをイベントとして受け取れる
    • ユースケース: @picoclaw 今日の作業を整理して のように、Slack チャンネル上で明示的に Bot を呼び出す運用
  • chat:write
    • 効果: Slack にメッセージを書き込める
    • ユースケース: ユーザーへの通常返信、スレッド返信、処理結果の通知
  • im:history
    • 効果: Bot との DM 内のメッセージ履歴を読める
    • ユースケース: 自分専用 Bot として 1 対 1 の会話をする、チャンネルではなく DM で安全に試す
  • files:write
    • 効果: Slack へファイルをアップロードできる
    • ユースケース: 生成したレポート、画像、ログ断片、添付ファイル付きの出力を返す
  • reactions:write
    • 効果: メッセージにリアクションを付けられる
    • ユースケース: 受信確認に eyes を付ける、完了時にチェックマークを付けるなど、軽い状態通知をする

任意スコープ

  • commands
    • 効果: Slash Command を受け取れる
    • ユースケース: /picoclaw help/picoclaw deploy のように、Slack のコマンド入力から起動したい場合
  • channels:history
    • 効果: public channel の通常メッセージ履歴を読める
    • ユースケース: メンションなしでも特定チャンネルの会話に反応させたい、運用チャンネルの発言を監視したい場合
  • groups:history
    • 効果: private channel の通常メッセージ履歴を読める
    • ユースケース: 限定メンバーの private channel で Bot を常駐させ、メンションなしでも反応させたい場合

通常は、まず app_mentions:read と DM だけで始める方が安全だと思う。チャンネルの全発言を読む構成にすると、意図しない反応範囲になりやすい。

5. Event Subscriptions を設定する

Event Subscriptions でイベントを有効にし、Bot Events を追加する。

最小構成なら次でよい。

  • app_mention
  • 何が起きるか: チャンネル内で Bot がメンションされたときにイベントが飛ぶ
  • どう使うか: もっとも安全な起動方法。Bot を呼びたいときだけ明示的に @bot を付ける
  • message.im
  • 何が起きるか: DM にメッセージが来たときにイベントが飛ぶ
  • どう使うか: 自分専用 Bot として使う場合の基本

必要に応じて追加するものは次のとおり。

  • message.channels
    • 何が起きるか: public channel の通常メッセージを受け取れる
    • どう使うか: メンションなしで反応させたい自動化用途。ただし反応範囲が広がるので注意
  • message.groups
    • 何が起きるか: private channel の通常メッセージを受け取れる
    • どう使うか: クローズドな運用チャンネルで常時監視させたい場合

6. App Home の Messages タブを有効にする

Slack 上で DM 的にやり取りしたい場合は、App Home の Messages タブを有効にしておく。

  • App Home を開く
  • Messages Tab を ON にする

7. ワークスペースへインストールする

設定後に Install App to Workspace を実行する。

ここで取得できる xoxb-...bot_token になる。

8. PicoClaw に設定する

{
  "channel_list": {
    "slack": {
      "enabled": true,
      "type": "slack",
      "allow_from": [
        "U0123456789"
      ],
      "reasoning_channel_id": "",
      "settings": {
        "bot_token": "xoxb-YOUR-BOT-TOKEN",
        "app_token": "xapp-YOUR-APP-TOKEN"
      }
    }
  }
}

Slack 権限の考え方

PicoClaw の Slack 連携では、実装上つぎの動作がある。

  • Socket Mode でイベント受信
  • メッセージ返信
  • DM 受信
  • メンション受信
  • リアクション追加
  • ファイル送信

このため、Slack 権限は「多めに積む」のではなく、使う動作に合わせて絞った方がよい。

専用 Bot を新規に作るなら、まずは次の組み合わせで始めるのが分かりやすい。

  • App-Level Token: connections:write
  • Bot Token Scopes:
    • app_mentions:read
    • chat:write
    • im:history
    • files:write
    • reactions:write

もし Slash Command を使わないなら commands は不要だし、メンション起動だけで運用するなら channels:historygroups:history も不要だ。

権限を増やすときの考え方

Slack の権限は、あとから用途が決まってから足す方が安全。

  • まずは DM とメンションだけで始める
  • その後、Slash Command が必要なら commands を追加する
  • メンションなし監視が必要になったら channels:historygroups:history を追加する

最初から広く権限を付けるより、Bot の反応範囲を明確に保ちやすい。

起動して Slack 接続を確認する手順

Slack App の設定と ~/.picoclaw/config.json の記述が終わったら、PicoClaw を起動して実際に接続できるか確認する。

1. 設定ファイルを確認する

最低限、次が入っていることを確認する。

{
  "channel_list": {
    "slack": {
      "enabled": true,
      "type": "slack",
      "allow_from": [
        "U0123456789"
      ],
      "settings": {
        "bot_token": "xoxb-YOUR-BOT-TOKEN",
        "app_token": "xapp-YOUR-APP-TOKEN"
      }
    }
  }
}

特に下記を確認する

  • bot_tokenxoxb- で始まっているか
  • app_tokenxapp- で始まっているか
  • token が channel_list.slack.settings 配下にあるか
  • allow_from に自分の Slack User ID を入れているか
  • enabled: true になっているか

2. PicoClaw を起動する

通常は gateway を起動する。

picoclaw gateway

デバッグしながら見たいなら次でもよい。

picoclaw gateway --debug

3. ログで接続成功を確認する

Slack との接続が成功すると、ログにはおおむね次のような内容が出る。

  • Starting Slack channel (Socket Mode)
  • Slack bot connected
  • Slack channel started (Socket Mode)

Slack bot connected が出ていれば、Bot Token と App Token の組み合わせで Socket Mode 接続できていると考えてよい。

systemd 常駐化している場合は service と health endpoint も確認する。

systemctl status picoclaw-gateway.service --no-pager -l
curl -fsS http://127.0.0.1:18790/health

/ready は内部状態の判定で 503 になることがあるため、Slack token の切り分けには Slack API を直接使う。

bot=$(jq -r '.channel_list.slack.settings.bot_token' ~/.picoclaw/config.json)
app=$(jq -r '.channel_list.slack.settings.app_token' ~/.picoclaw/config.json)
curl -fsS -H "Authorization: Bearer ${bot}" https://slack.com/api/auth.test
curl -fsS -X POST -H "Authorization: Bearer ${app}" https://slack.com/api/apps.connections.open

4. Slack 上で疎通確認する

最初の確認は DM か、Bot をメンションしたメッセージが分かりやすい。

5. 返信とリアクションを確認する

正常なら次のどちらか、または両方が見える。

  • Bot からの返信
  • 受信確認用のリアクション

実装上、PicoClaw は受信時や完了時にリアクションを付けることがある。返信だけでなくリアクションも確認対象にすると分かりやすい。

6. うまくいかないときの確認ポイント

起動直後に接続できない

まずはトークンと Socket Mode を確認する。

  • bot_token が誤っていないか
  • app_token が誤っていないか
  • Slack App 側で Socket Mode が有効か
  • App-Level Token に connections:write が付いているか

Slack で送っても反応しない

次を順に見る。

  • allow_from に自分の ID が入っているか
  • Event Subscriptions が有効か
  • app_mentionmessage.im を追加したか
  • App をワークスペースに再インストールしたか

権限やイベントを追加したあと、再インストールしないと反映されないことがある。

チャンネルでは反応しないが DM では反応する

この場合は設計どおりのことも多い。

  • app_mentions:read はあるか
  • チャンネルでちゃんとメンションしているか
  • Bot がそのチャンネルに参加しているか

メンションなしの通常メッセージに反応させたいなら、追加でイベントや履歴権限が必要になる。

7. 最初の運用方針

最初は次の形で試すのが安全だ。

  1. DM だけで疎通確認する
  2. 次にメンション起動を確認する
  3. それで足りない場合だけ権限を増やす

いきなりチャンネル全体を監視する構成にするより、反応範囲を限定したまま動作確認した方が問題を切り分けやすい。

tools はまずデフォルトを信頼する

PicoClaw はツール群も多いが、初手で全部を触る必要はない。

特に把握しておくとよいのは次のあたり。

  • tools.web
  • tools.exec
  • tools.skills
  • tools.mcp
  • tools.allow_read_paths
  • tools.allow_write_paths

Web 検索は DuckDuckGo が既定で有効な構成になっており、追加で Brave や Tavily などを有効化できる。検索品質や取得元を調整したくなってから tools.web を明示すればよい。

exec には危険コマンドを止める deny パターンがあるので、最初はそのまま使うのが無難だ。

mcp は必要になるまで切る

MCP サーバをつなぐとできることは増えるが、構成も一気に複雑になる。

最初の方針としてはこうしておくのが扱いやすい。

{
  "tools": {
    "mcp": {
      "enabled": false
    }
  }
}

あとから必要になったら、servers を 1 個ずつ増やす方がトラブルを追いやすい。いきなり複数の MCP サーバを混ぜない方がよい。

k3s 状態確認 MCP は read-only から始める

Ubuntu Desktop の PicoClaw から自宅 staging k3s を見る場合は、最初から操作権限を渡さない。

方針は次の通り。

  • 対象は staging k3s のみにする
  • MCP server は --read-only で起動する
  • kubeconfig は専用 ServiceAccount のものを使う
  • RBAC でも get/list/watchpods/log 程度に絞る
  • SecretConfigMap は初期状態では読ませない
  • prod を見る場合は別 kubeconfig / 別 MCP server 名にする

この二重の read-only は重要だ。MCP server 側の実装ミスや設定漏れがあっても、Kubernetes API server 側の RBAC で最後に止められるからだ。

Ansible 側では ubuntu_desktop_staging_k8s profile を使う。現行 profile では k8s-status に加えて、npm / node / npx を使わない自前 Python MCP の fetchsearchsystemd-statussqlite-stategit-status も有効化する。

gatewayheartbeat

ローカルで触るだけなら gateway.host127.0.0.1 のままが安全だ。

{
  "gateway": {
    "host": "127.0.0.1",
    "port": 18790
  },
  "heartbeat": {
    "enabled": true,
    "interval": 30
  }
}

外部から Webhook を受ける必要があるときだけ、公開方法をよく考えたうえで 0.0.0.0 を検討する。

heartbeat はワークスペース内の HEARTBEAT.md を使う機能なので、定期実行を使わないなら急いで凝った設定にしなくてよい。

CLI 型モデルを使う場合

API キー型だけでなく、CLI 型のモデル定義も model_list に寄せて考えられる。

{
  "agents": {
    "defaults": {
      "workspace": "/home/your-user/.picoclaw/workspace",
      "restrict_to_workspace": true,
      "model_name": "codex-cli-spark"
    }
  },
  "model_list": [
    {
      "model_name": "codex-cli-spark",
      "provider": "codex-cli",
      "model": "gpt-5.3-codex-spark",
      "workspace": "/home/your-user/.picoclaw/workspace"
    }
  ]
}

provider: "codex-cli" の場合、model は PicoClaw から codex exec -m <model> へ渡される。Slack bot の応答速度を優先するなら gpt-5.3-codex-spark を既定にする。

codex-cli の workspace は絶対パスで書く。model_list[].workspace~/.picoclaw/workspace を書くと、PicoClaw 側で ~ が展開されず codex cli error: No such file or directory になることがある。

環境変数で上書きする考え方

複数環境を切り替えたいときは、設定ファイルを直接書き換えるより環境変数の方が扱いやすい。

代表的なのは次の 2 つ。

  • PICOCLAW_CONFIG
  • PICOCLAW_HOME
PICOCLAW_CONFIG=/etc/picoclaw/config.json picoclaw gateway
PICOCLAW_HOME=/srv/picoclaw picoclaw agent

最初に避けたい設定

最初の段階では次のような構成は避けた方がよい。

  • providers を主設定として使い続ける
  • 使わないチャネルまで全部 enabled: true にする
  • allow_from を空のまま公開チャネルにつなぐ
  • gateway.host を理由なく 0.0.0.0 にする
  • mcp を複数サーバ付きでいきなり有効化する

まとめ

現行の PicoClaw 設定は、全部入りのサンプルをそのまま使うより、次の順で積み上げると分かりやすい。

  1. model_list で 1 つモデルを定義する
  2. agents.defaults.model_name を合わせる
  3. 必要なチャネルを 1 つだけ有効化する
  4. allow_from でアクセス制限する
  5. 必要になったら toolsmcp を増やす