# 実例: Box を作って運用する コピペ可能な end-to-end 実例。すべて実挙動に基づく。`box_id` の実値は環境依存なので、**まず `atasira_list_boxes()` を呼んで実在の box_type / DB id を確認**してから使うこと(例中の値をハードコードしない)。 --- ## (A) 監視+通知 Box(market-watch — 実稼働中の実例、box-fulfill 経路) **intent(人間の発話例)**: 「ヤフオク+メルカリで FD3S 純正のインタークーラー用ラバージョイント(マツダ純正品番 N3F1-13-245C)の中古を監視して、送料込み 1 万円未満のが出たら LINE で教えて。」 ### 1. box_type 選定(feasibility 事前チェック) 既存 `market-watch` が `os_operations: [browser:navigate/click/type/scroll/screenshot/tab_manage, screenshot:capture, op:read, notify:email, notify:line]`、`network: filtered`、`url_allowlist: [auctions.yahoo.co.jp, jp.mercari.com, page.auctions.yahoo.co.jp]` を既承認 → capability gap 無し。 ```bash curl -sS -X POST "$ATASIRA_BFF_URL/api/v1/boxes/feasibility" \ -H "Authorization: Bearer $ATASIRA_PAT" -H "Content-Type: application/json" \ -d '{"box_type": "market-watch", "task_description": "ヤフオク/メルカリで FD3S 純正ラバージョイントを監視し LINE 通知"}' # -> missing_capabilities: [] ⇒ box-fulfill でよい(新 C9 draft 不要) ``` ### 2. manifest 運用設定を投入(`src/manifests/market-watch.yaml` を直接編集) capability キー(`tools`/`os_operations`/`network`)には触れない。`config_defaults`/`trigger_type`/`trigger_schedule`/`purpose`/`prohibited_actions`/`credentials`/`notify` のみ。実稼働 manifest の構造(抜粋・実ファイル準拠): ```yaml box_type: market-watch agent_kind: worker config_defaults: watch_items: - label: "FD3S純正 インタークーラー/吸気配管 ラバージョイント (N3F1-13-245C)" part_number: "N3F1-13-245C" sites: ["auctions.yahoo.co.jp", "jp.mercari.com"] broad_search_terms: ["FD3S","RX-7","純正","インタークーラー","吸気","ジョイント","ラバー","13B"] exclude_terms: ["GReddy","TRUST","HKS","BLITZ","アルミ","シリコン","汎用","ワンオフ","キット"] condition: "中古" max_total_price_jpy: 10000 # 送料込み合計 search_urls: - "https://auctions.yahoo.co.jp/search/search?p=FD3S%20インタークーラー%20ジョイント" - "https://auctions.yahoo.co.jp/search/search?p=FD3S%20インタークーラー%20純正" dedup: "通知済み出品IDを保持し二重通知を防止する" exclude_sellers: [] purchase_enabled: false trigger_type: schedule trigger_schedule: "*/15 * * * *" # ToS 配慮の 15 分間隔 purpose: >- ヤフオク+メルカリを15分毎に監視。FD3S(RX-7/13B-REW)の純正インタークーラー用 "ラバージョイント"(マツダ純正品番 N3F1-13-245C)の中古を探す。品番はほぼ書かれない ため広い検索語で候補を拾い、各候補を開いてタイトル・説明・写真から純正ラバー ジョイントか判定する。社外品(GReddy/TRUST/HKS/BLITZ/アルミ/シリコン/汎用/ワンオフ/ キット)と別部品の純正金属パイプは除外する。送料込み合計が1万円未満のもののみ通知。 既通知の出品ID・exclude_sellers 記載の出品者は除外。条件一致で notify:line 通知。 購入・入札は一切行わない(通知のみ)。15分を超える高頻度アクセスはしない。 prohibited_actions: - 購入/入札/支払いボタンを人間承認なしに押下しない(コードゲートでも強制) - url_allowlist 以外のサイトへ遷移しない - 設定した価格上限(送料込み1万円未満)を超える出品を通知しない credentials: allowed_vaults: ["PJ_Dashboard"] token_env_var: "OP_SERVICE_ACCOUNT_TOKEN" notify: line: vault: "PJ_Dashboard" item: "atasira-line-bot" # 1Password item(channel access token) broadcast: true # recipients 未宣言 = LINE公式アカウント友だち全員へ配信 ``` > **必須(`02-box-lifecycle.md` §2.1)**: `config_defaults.watch_items` を書くだけでは Box は条件を認識しない。**必ず具体条件を `purpose` に自然文で書く**(上記の通り)。これが LLM に確実注入される唯一の経路。 ### 3. secret 取得(エージェントが実施・平文を manifest に書かない) `atasira-line-bot` item が 1Password の `PJ_Dashboard` vault に無ければ、`/browser-po-auth`(LINE Developers コンソール)で PO にログインを仰ぎ channel access token を発行 → `/op-sa-write` で vault に保存。manifest には **vault 名 / item 名のみ**。`notify.line.vault` は必ず `credentials.allowed_vaults` にも含める(二重ゲート)。 ### 4. ガバナンス確認 変更したのは `config_defaults`/`trigger_*`/`purpose`/`prohibited_actions`/`credentials`/`notify` のみ。`tools`/`os_operations`/`network` は無変更 → capability 拡大ではないため **C9 draft 不要・直接適用可**(`02-box-lifecycle.md` §3 の境界表に一致)。 ### 5. 反映 + 検証 ``` # ドライラン: 現在の監視条件を Box に要約させる atasira_send_instruction(box_id="market-watch", message="今の監視対象を要約して") atasira_get_responses(box_id="market-watch", session_id="<返ってきた session_id>") ``` 応答に品番 N3F1-13-245C・送料込み 1 万円未満・社外品除外が反映されていれば OK。可能なら `notify:line` を 1 回テスト送信し、1Password 経路と配信を確認。最後に人間へ「監視条件/頻度/通知先/購入無し」を要約報告する。 --- ## (B) 既存 Box を運用する(list → status → instruct → responses) ``` # 1) 可視 Box 一覧(実在の box_type / DB id を確認) atasira_list_boxes() # 2) 1 つの Box の状態(state / last_heartbeat) atasira_box_status("market-watch") # 3) 指示を送る(新規会話 = session_id 省略。応答は同じ呼出で返る) atasira_send_instruction(box_id="market-watch", message="直近24hの検知件数と通知内容を報告して") # 4) 後から履歴を読み直す(3 が返した session_id を使う) atasira_get_responses(box_id="market-watch", session_id="a1b2c3...") ``` - 3 で 403 → その Box の primary/secondary assignment(または admin role)が無い。`/box-ops` の user-assignments で付与するか admin に依頼(`03-mcp-tools.md` §4)。 - pause/resume/kill は admin/operator のみ `POST /api/v1/boxes/<box_id>/control`(MCP ツール無し)。 --- ## (C) Box の LLM ノードを m1 に切替 → 既定へ戻す `box_id` は **DB id**(`atasira_list_boxes()` が返す `id`)。node は provider=atsllm のときのみ効く。 ``` # 現状確認(effective_node / node_source / available_nodes) atasira_get_box_llm(box_id="<db id>") # 公開プラットフォームノード m1 へ atasira_set_box_llm(box_id="<db id>", node="m1") # 検証: node_source が "db_override"、effective_node が "m1" になる atasira_get_box_llm(box_id="<db id>") # 既定(このホストの m5)へ戻す = node override 解除 atasira_set_box_llm(box_id="<db id>", node="none") ``` 注意(`04-llm-provider-node.md`): - PUT は admin または box primary のみ(それ以外 403)。 - 未 configured node は HTTP 400(fail-closed)。先に `available_nodes[].configured` を確認。 - `m1` は同時実行上限が低い(`max_num_seqs=1`)。高並列用途は `m5` を維持。 - 反映: task 実行経路は heartbeat 経由 ~30 秒、chat/session 経路は次メッセージから即時。 --- ## 新規 capability が要る場合(box-create / C9 draft へ) もし intent が既存 Box に無い新 capability(例: `shell:exec` で自動入札 CLI を叩く)を要求するなら、box-fulfill ではなく `/box-create` で C9 draft を起票する: ``` atasira_create_box_draft( purpose="...", box_type="market-bid", os_operations=["browser:navigate","browser:click","shell:exec"], tools=["Read"], url_allowlist=["auctions.yahoo.co.jp"], prohibited_actions=["人間承認なしに入札しない"], allow_network=True, ) # shell:exec は over_limit 対象 → 応答 over_limit: true(エラーではない) ``` 人間 admin が `GET /api/v1/boxes/box-drafts/pending` で `over_limit_ops: ["shell:exec"]` を確認し、`POST /api/v1/boxes/box-drafts/<draft_id>/approve` に `{"confirm_over_limit": true}`(二段承認)で活性化。承認後に `src/manifests/market-bid.yaml` が書かれ Box が `state: idle` になり、以降は (A) と同じ box-fulfill でパラメータ調整できる。詳細は `02-box-lifecycle.md`。