わたしの、最高の相棒、Codex CLI

わたしの、最高の 相棒、Codex CLI

Event:

Codexどう使ってる?期待通りにいかない時の向き合い方と工夫

Presented:

2026/03/06 nikkie

お話しすること🗣️

  1. Codex自走事例

  2. 使った仕組み: Rules

  3. 裏側の実装にdive

お前、誰よ(Python使いの自己紹介)

../_images/uzabase-white-logo.png

Claude CodeやCodex CLIについて発表

コーディングエージェントについての見解

Claude Code:

わたしの、最高の [2]

Codex CLI:

わたしの、最高の 相棒

あくまで2026年3月初頭時点です

Codex CLI 自走 事例

「DBをdockerで立てて、APIを別で立てて、curlして、その後DBをdumpして」を20回くらい

🏃‍♂️のスライドはCodex CLIの話ではないため、詳細が理解できなくても大丈夫です

Agent Development Kit 🏃‍♂️

adk create 🏃‍♂️

search_agent/agent.py
root_agent = Agent(
    model='gemini-3.1-pro-preview',
    name='search_agent',
    instruction="You are a helpful assistant with access to Google Search. (略)",
    tools=[google_search],
)

adk web 🏃‍♂️

../_images/adk-web-screenshot.png

マイナーバージョンアップで壊れる 🏃‍♂️

  • adk-python は隔週リリース(現在 1.26.0)

  • ADKのバージョンを上げる(uv sync -P google-adk

  • Web UIは起動する

  • 実行時にエラー

../_images/adk-miner-version-up-runtime-error.png
応答がなく、エラーが出ている
INFO:     127.0.0.1:61263 - "POST /run_sse HTTP/1.1" 500 Internal Server Error

sqlalchemy.exc.ProgrammingError: (psycopg.errors.UndefinedColumn) column events.custom_metadata does not exist

[SQL: SELECT events.id AS events_id, events.app_name AS events_app_name, events.user_id AS events_user_id, events.session_id AS events_session_id, events.invocation_id AS events_invocation_id, events.author AS events_author, events.actions AS events_actions, events.long_running_tool_ids_json AS events_long_running_tool_ids_json, events.branch AS events_branch, events.timestamp AS events_timestamp, events.content AS events_content, events.grounding_metadata AS events_grounding_metadata, events.custom_metadata AS events_custom_metadata, events.usage_metadata AS events_usage_metadata, events.citation_metadata AS events_citation_metadata, events.partial AS events_partial, events.turn_complete AS events_turn_complete, events.error_code AS events_error_code, events.error_message AS events_error_message, events.interrupted AS events_interrupted
FROM events
WHERE events.app_name = %(app_name_1)s::VARCHAR AND events.user_id = %(user_id_1)s::VARCHAR AND events.session_id = %(session_id_1)s::VARCHAR ORDER BY events.timestamp DESC]
[parameters: {'app_name_1': 'search_agent', 'user_id_1': 'user', 'session_id_1': '3e967de9-05aa-4d53-bd07-aad4daf0c25d'}]
(Background on this error at: https://sqlalche.me/e/20/f405)

なぜマイナーバージョンアップで壊れるのか 🏃‍♂️

  • ORMの実装が変わっている (カラム追加)

  • 一方DBのテーブル定義は古いまま

  • 新しいカラムを SELECT で指定しているが、テーブルになく、実行時にエラー

バージョンごとにテーブル定義を知りたい

  • sqldef というツールを知っていた

  • 2つのテーブル定義から ALTER TABLE を自動で作る

  • 💡ADKのマイナーバージョンアップと合わせて ALTER TABLE もやれば、実行時エラーなくなるのでは

テーブル定義 のdump作業

  1. DB起動

  2. ADKサーバ起動

  3. HTTPリクエスト(=空のテーブル作成)

  4. テーブル定義のdump

DB起動・終了

$ docker ps
$ docker run --name adk-pg -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d postgres:18
$ docker rm -f adk-pg

docker 操作

ADKサーバ起動

$ nohup uvx --from google-adk==1.22.0 adk api_server \
    --session_service_uri postgresql+psycopg://postgres:mysecretpassword@localhost:5432/postgres
$ lsof -ti :8000
$ kill <pid>

残りのコマンド

$ curl -X POST http://127.0.0.1:8000/apps/my_agent/users/test_user/sessions \
    -H 'Content-Type: application/json' -d '{}'

$ psqldef -h localhost -p 5432 -U postgres -W mysecretpassword \
    postgres --export > schemas/v<version>/postgresql.sql

まずペアプロ

  • 対話的に AGENTS.md を作成。ここまでのコマンドを列挙した 手順書

  • 1つバージョンを指定して、コマンド実行を都度許可しながら一緒に作業

  • AGENTS.md 更新や、シェルスクリプトによる自動化を必要に応じて依頼

やや脱線:Codex CLIの作業から 学ぶ 🏃‍♂️

  • git status -sb

  • 起動したサーバのログの保存(nohup uvx adk api_server > server.log 2>&1

  • ログファイルを見て調査している!

IMO:Codex CLIは シェル芸人

Rules

OpenAI Learning Lab: Codex を使いこなす より

  • 「Codexがいちいち承認を求めてきてテンポが悪い -> Rules で事前承認」(40:30〜)

  • ~/.codex/rules/ やプロジェクトの .codex/rules/ に置く

  • codex execpolicy check

Rules(途中の状態)

prefix_rule(pattern=["docker", "ps"], decision="allow")
prefix_rule(pattern=["scripts/export_schema.sh"], decision="allow")
prefix_rule(pattern=["docker", "rm", "-f"], decision="allow")
prefix_rule(pattern=["git", "add"], decision="allow")
prefix_rule(pattern=["git", "commit"], decision="allow")
prefix_rule(pattern=["kill"], decision="allow")

手順書に従って Codex CLI が実行するコマンドを 事前許可

🌟 スクリプト にさらにまとめればいいじゃん!

prefix_rule(pattern=["scripts/export_schema.sh"], decision="allow")
prefix_rule(pattern=["git", "add"], decision="allow")
prefix_rule(pattern=["git", "commit"], decision="allow")

スクリプト(抜粋)

api_pid="$(cat "$current_pidfile")"
kill "$api_pid" >/dev/null 2>&1 || true

docker rm -f "$current_container" >/dev/null 2>&1 || true

なぜスクリプトにまとめたか

  • docker rm -fkill を任意の引数で実行できちゃうのはリスク(Codexは賢いのでめったになさそうだが)

  • スクリプトであれば前方一致だけでなく 引数までコントロールできる

  • 放置して達成! [3]https://github.com/ftnext/adk-python-db-schema-history

yorifujiさん記事から:Rulesは [] をネストしても書けます

# Before
prefix_rule(pattern=["git", "add"], decision="allow")
prefix_rule(pattern=["git", "commit"], decision="allow")
# After
prefix_rule(pattern=["git", ["add", "commit"]], decision="allow")

execpolicyのREADME にあります

まとめ🌯 繰り返し作業を Rules で自走

  • 「DBをdockerで立てて、APIを別で立てて、curlして、その後DBをdumpして」を20回くらい

  • AGENTS.md に手順書を作り、自動化スクリプトも書かせていく

  • Rules で前方一致でマッチよりもスクリプトに入れたほうがより安全にできた例

Dive:コマンド実行許可の裏側

v0.110.0のソースコードリーディングより [4]

Codex CLIのセキュリティ

  • Sandbox mode: シェルコマンドを安全に 実行

  • Approval policy: シェルコマンドの実行 許可を尋ね させて安全に

https://developers.openai.com/codex/security#sandbox-and-approvals

Codex CLIのオプション

  • Sandbox mode: --sandbox, -s

  • Approval policy: --ask-for-approval, -a

https://developers.openai.com/codex/cli/reference#global-flags

#codex_findy より(2025/10)

codex (フラグなし)

projectを trust (Do you trust the contents of this directory?)

  • Sandbox: workspace-write [5]

  • Approval: OnRequest [6]

シェルコマンドの実行許可

  1. ルールにあればルールのdecisionとなる

  2. ルールにない場合のフォールバック処理

https://github.com/openai/codex/blob/rust-v0.110.0/codex-rs/core/src/exec_policy.rs#L199

SandboxとApprovalに基づくフォールバック

コマンドはsandboxで実行

  • Approval: OnRequestでは、コマンドが失敗した時sandboxの外での実行は しない

  • (コマンドが失敗した時にsandbox外で実行させることもできます。自走tips)

https://github.com/openai/codex/blob/rust-v0.110.0/codex-rs/core/src/tools/orchestrator.rs#L232

小まとめ:コマンド実行許可の裏側

  • Rulesのpatternやdecisionが優先される

  • Rulesに無いコマンドは、sandboxやapprovalに基づいて処理(通常はworkspace-write・OnRequest)

ご清聴ありがとうございました!

Happy Python Development♪