nagi-ledger
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nagi-ledgershow me the latest session report"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
nagi-ledger
日本語 | English
自律型 AI コーディングエージェントのための監査台帳とガードレール。 MCP サーバー + Claude Code hooks。MCP SDK を除いて標準ライブラリのみで動きます。
AI エージェントに単独で作業をさせると、2 つの問いに答えられなくなります。
実際に何をしたのか。 どのサブエージェントを派遣し、何回リトライし、検証は何と結論したのか。
同じ失敗をどう止めるのか。 月曜に判明した行き止まりが、金曜にまた試される。何も覚えていないからです。
nagi-ledger はこの両方に答えます。そして重要なのは、エージェントの自制心に頼らず、機構として答える点です。派遣はエージェント自身が制御できない hook が記録します。既知の行き止まりは次の試行の前に照会され、該当すれば試行そのものが阻止されます。
記憶するよう指示された規則は、単なる提案にすぎない。 ハーネスが強制する規則だけが、制約になる。
何をするものか
flowchart LR
subgraph session["コーディングセッション"]
direction TB
S["セッション開始"] --> D["サブエージェントを<br/>派遣しようとする"]
D --> R["サブエージェントが動く"]
R --> F["ツールが失敗する"]
F --> E["ターンを終えようとする"]
end
S -. "未解決の作業を注入" .-> B["session_brief"]
D -. "履歴を照会" .-> G["dispatch_guard<br/>繰り返しを阻止"]
R -. "自動記録" .-> H["hook_ingest"]
F -. "自動記録" .-> H
E -. "まだ終わってない?" .-> Q["goal_gate<br/>停止を阻止"]
B --> L[("SQLite 台帳")]
G --> L
H --> L
Q --> L構成要素は 6 つ。それぞれエージェントのライフサイクルの別々の地点に接続されます。
構成要素 | フック | 役割 |
|
| 未解決の作業をセッション開始時に注入します。進行中の目標、検証待ちの派遣、直近の行き止まり、未コミットの変更が残るリポジトリ。すべて片付いているときは何も出力しません。つまり、綺麗な状態のセッションではコンテキストを 1 バイトも消費しません。 |
|
| サブエージェントを派遣する直前に、そのタスクのリトライ回数と記録済みの行き止まりを照会します。リトライ上限を超えている場合、または既知の行き止まりに該当する場合は、理由を添えて阻止します (exit 2)。それ以外のときは沈黙します。 |
|
| すべてのサブエージェント派遣とツール失敗を台帳に記録します。非同期で走り、エージェントに拒否権はありません。 |
|
| 目標が設定されている間、エージェントがターンを終えることを阻止します ( |
| MCP (stdio) | 台帳を 10 個の MCP ツールとして公開します。エージェントが意図的に台帳を読み書きするための口です。検証結果の記録、行き止まりの登録、セッションレポートの生成など。 |
| (フックではない、手動 CLI) | 台帳全体を 1 つの JSON に読み取り専用でエクスポートします。ledger-view — 素の TS SPA — がこの JSON を読んで台帳を可視化します。 |
台帳の本体 (ledger.py) は MCP のコードもフックのコードも一切含まない依存ゼロのモジュールです。そのため、すべての関数を直接ユニットテストできます。
Related MCP server: agent-activity
出力言語について
session_brief.py が SessionStart/PostCompact で注入するブリーフィング — ## 開いてるループ、### アクティブ goal、### 検証待ち、### 直近の dead-end、### 未 commit といった見出し — は日本語で固定されており、セッション開始のたびにエージェントのコンテキストへそのまま入ります。ledger_session_report という MCP ツール (ledger.py の session_report()) も同様で、Markdown の見出しは ## 自律実行リスト です。
これはドキュメント不足というより、このプロジェクトの前提そのものです。開発者本人が日常的に日本語で使っているツールであり、翻訳はされていません。今のところ英語に切り替える手段はありません (NAGI_LANG のような環境変数は存在しません)。
それ以外は英語です。goal_gate.py 自身の出力 (stop-gate の阻止理由、CLI のメッセージ、status) は英語のテンプレートで、日本語が混じり得るのは set で登録した goal テキスト自身がそのままエコーされる場合だけです — それはスクリプトの言語ではなく、あなたの入力です。dispatch_guard.py の阻止理由も英語の枠組みに、記録した dead-end の理由 (あなた自身が書いた言語) が差し込まれる形です。hook_ingest.py は標準出力に何も書かず、デバッグ用の行だけを stderr に書きます。注入される日本語が困る場合は、session_brief.py を接続しない、ledger_session_report を呼ばないようにしてください。それ以外の要素にはこの問題はありません。
なぜ「指示」ではなく「フック」なのか
このプロジェクトが立脚している設計原則です。
エージェントが覚えていなければならない規則は、提案にすぎない。 ハーネスが強制する規則だけが、制約になる。
プロンプトに 「同じ失敗する手法を 2 回を超えて繰り返さないこと」 と書くことはできます。それはコンテキストが長くなるまで、あるいはモデルが自信を持つまで、あるいは要約がその一行を落とすまでは有効です。dispatch_guard は同じ規則を exit 2 にします。
この方針から、実装上の判断が 2 つ導かれました。
ガードは必ず「開く方向」に倒れる (fail open)
すべてのフックは、内部エラーが起きたら必ず exit 0 で終了します。全部の派遣を阻止する壊れたガードは、ガードが無いより悪いからです。クラッシュも、データベースの欠損も、ファイルロックも、すべて「通す。ただし stderr に文句を書く」に解決されます。
ただし fail open が原理的に不可能な箇所が 1 つあります。SessionStart フックが標準入力で待ちに入った場合、例外ハンドラでは救えません。 例外が発生しないからです。ただ固まり、セッションが永遠に始まらないだけです。この経路は「標準入力を一切読まない」ことで塞いであり、開いたまま閉じられていないパイプに対してスクリプトを起動する回帰テストで守っています。
dispatch_guard の阻止は JSON ではなく終了コードで伝える
初期の実装では permissionDecision: "ask" という JSON を返していました。しかし Claude Code の auto 権限モードでは、この判断は黙って握りつぶされます。 ガードは正しく判断したのに、派遣はそのまま実行され、理由は誰にも届きませんでした。
終了コード 2 はすべての権限モードで尊重されます。届かないガードは、ガードではありません。
これは PreToolUse と permissionDecision: "ask" に固有の話であり、ここにあるすべてのフックに対する一般則ではありません。goal_gate.py の Stop フックは自分のイベント種別に合った別の (正しい) 仕組みを使っています。{"decision": "block", "reason": "..."} を標準出力に出して exit 0 で終了する、これが Stop フック自体が定める契約どおりの動きです (上の構成要素の表を参照)。stop-gate を手で実行してこの JSON と exit 0 を見ても、それは上記の原則と矛盾しているわけではなく、イベント種別が違えばプロトコルも違う、というだけです。
使い方
Python 3.10 以上が必要です。
git clone https://github.com/namakoo-dev/nagi-ledger.git
cd nagi-ledger
python -m venv .venv
.venv/bin/pip install -r requirements-dev.txt # Windows: .venv\Scripts\pip
.venv/bin/pytest -qrequirements.txt には実行時の唯一の依存 (MCP SDK、server.py のみが必要とします) が入っています。requirements-dev.txt はそれに pytest を加えたものです。
MCP サーバーを登録する
claude mcp add nagi-ledger -s user -- /abs/path/.venv/bin/python /abs/path/server.pyMCP サーバーには mcp パッケージが必要なので、仮想環境側のインタプリタを指定してください。一方フックのスクリプトは意図的に標準ライブラリのみで書かれているため、どの Python でも動きます。
フックを接続する
~/.claude/settings.json に以下を追加します。PY をインタプリタのパス、DIR をチェックアウト先のパスに置き換えてください。
{
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "PY DIR/session_brief.py", "timeout": 15 }] }
],
"PostCompact": [
{ "hooks": [{ "type": "command", "command": "PY DIR/session_brief.py", "timeout": 15 }] }
],
"PreToolUse": [
{ "matcher": "Agent|Task",
"hooks": [{ "type": "command", "command": "PY DIR/dispatch_guard.py", "timeout": 15 }] }
],
"PostToolUse": [
{ "matcher": "Agent|Task",
"hooks": [{ "type": "command", "command": "PY DIR/hook_ingest.py agent-dispatch", "timeout": 30, "async": true }] }
],
"PostToolUseFailure": [
{ "hooks": [{ "type": "command", "command": "PY DIR/hook_ingest.py tool-failure", "timeout": 30, "async": true }] }
],
"Stop": [
{ "hooks": [{ "type": "command", "command": "PY DIR/goal_gate.py stop-gate", "timeout": 15 }] }
]
}
}SessionStart と PostCompact に同じスクリプトを渡しています。圧縮はセッション開始と同じ状況、つまり未解決の作業が文脈から失われた状態を作るため、必要な処置も同じです。
各要素は独立しています。必要なものだけ接続して構いません。
フックを手で試す
各フックスクリプトは標準入力から JSON オブジェクトを 1 つ読みます。Claude Code が PostToolUse/PreToolUse で流し込むのと同じ形です。つまり、実際の派遣を待たなくても、手で流し込んで行が入るところを見られます。以下の例では tool_name: "Agent" を使っています。これは上の dispatch_guard の PreToolUse マッチャーと hook_ingest.py/dispatch_guard.py 側のチェックに合わせたものです。お使いの環境でサブエージェント派遣ツールの名前が違う場合は、フックを接続する のマッチャーとこのチェックの両方を、実際に Claude Code が送ってくる名前に合わせてください — 信用する前に、実際のフックイベント JSON を確認してください。
1. hook_ingest.py agent-dispatch — 派遣を記録する
echo '{
"tool_name": "Agent",
"tool_input": {
"subagent_type": "general-purpose",
"model": "sonnet",
"description": "fix the flaky widget test",
"prompt": "Investigate and fix the flaky test in test_widget.py."
}
}' | PY DIR/hook_ingest.py agent-dispatchexit 0 で終わり、標準出力には何も出ません (stderr にはデバッグ用に dispatch_id=1 が出ます)。行が入ったことを確認するには:
sqlite3 ~/.nagi/ledger.db "select id, task, agent_type, model from dispatches order by id desc limit 1;"tool_input が無い、tool_name が "Agent" 以外、tool_input が JSON オブジェクトでない、といった形は「記録すべきものが無い」として黙って何もしません (それでも exit 0、行数 0) — これはバグではなく意図的な設計です。上の「ガードは必ず『開く方向』に倒れる」を参照してください。
2. hook_ingest.py tool-failure — 失敗したツール呼び出しを記録する
echo '{
"tool_name": "Bash",
"tool_input": {"command": "pytest -q"},
"tool_response": {"error": "1 failed, 2 passed"}
}' | PY DIR/hook_ingest.py tool-failureactions に 1 行挿入されます (tier=0、category=tool_failure、description="Bash: 1 failed, 2 passed")。
3. dispatch_guard.py — 繰り返された派遣を阻止する
手順 1 と同じ agent-dispatch ペイロードを hook_ingest.py にあと 2 回 (同じ description で計 3 回) 流し込んでそのタスクのリトライ回数を上限に到達させ、続けて同じペイロードを PreToolUse イベントとして dispatch_guard.py に送ります。
PAYLOAD='{
"tool_name": "Agent",
"tool_input": {
"subagent_type": "general-purpose",
"model": "sonnet",
"description": "fix the flaky widget test",
"prompt": "Investigate and fix the flaky test in test_widget.py."
}
}'
echo "$PAYLOAD" | PY DIR/hook_ingest.py agent-dispatch # 2 回目の派遣
echo "$PAYLOAD" | PY DIR/hook_ingest.py agent-dispatch # 3 回目の派遣
echo "$PAYLOAD" | PY DIR/dispatch_guard.py # ここで阻止される
echo "exit=$?"BLOCKED by dispatch_guard.
Task: fix the flaky widget test
prior dispatches: 3, last verdict: PENDING
Budget rule: same-purpose retries are limited to 2.
Proceed only if you have new information that invalidates the above; otherwise change approach or stop.
exit=2目標ゲートを使う
python goal_gate.py set "全テストが緑で CHANGELOG が更新されていること" --max-turns 20
python goal_gate.py status
python goal_gate.py extend 10 # バックグラウンド処理の完了待ちで予算が足りないとき
python goal_gate.py done "214 テスト緑、CHANGELOG を a1b2c3d でコミット"done を宣言するまで (あるいは abort するか、ターン予算が尽きるまで)、エージェントはターンを終えられません。
台帳を JSON でエクスポートする
python export_json.py # 既定 DB を標準出力へ
python export_json.py --out ledger.json
python export_json.py --db /path/to/other/ledger.dbactions / dispatches / approaches の全行を、間引きなしで 1 つの JSON にまとめます。台帳を書き換えることは決してありません (読み取り専用で開きます)。対象の DB が存在しない場合は空の DB を作らず、stderr に理由を出して exit 1 します。
出力は ledger-view — 素の TS SPA — でそのまま可視化できます。
MCP ツール一覧
ツール | 用途 |
| 自律実行した操作を記録する。影響度を 0〜2 の 3 段階で区別。 |
| サブエージェントの派遣を記録し、そのタスクのそれまでのリトライ回数を返す。 |
| 派遣に |
| そのタスクのリトライ回数、直近の検証結果、リトライ上限超過フラグを返す。 |
| 試した手法を |
| そのタスクで既に何を試し、結果がどうだったかを返す。 |
| 直近の操作と派遣を Markdown レポートにする。 |
| 影響度・分類・検証結果ごとの集計。 |
| actions/dispatches/approaches を横断キーワード検索し、本文を含まない索引行だけを返す。 |
| 完全一致では拾えない、言い回しが違う重複タスクを類似度で検出する。 |
派遣の記録は自動です (フックがやります)。一方、検証結果の記録は意図的に手動のままにしてあります。「その仕事が本当に正しいか」を決めるのは判断であり、そこを自動化したらこの仕組みの意味が失われるからです。
データの保存先
~/.nagi/ledger.db に SQLite で保存します。テーブルは actions / dispatches / approaches の 3 つ。
WAL モードを使っています。非同期フックが同時に発火しうるためで、書き込みが 1 件失われることは監査証跡に穴が開くことを意味するからです。
すべてのパスは環境変数で上書きできます。テストスイートが実際の台帳に触れないのも、この仕組みを使っています。
環境変数 | 既定値 |
|
|
|
|
|
|
| 現在の git リポジトリ (あれば) |
テスト
.venv/bin/pytest -q # Windows: .venv\Scripts\pytest; 214 テスト
.venv/bin/python tests/smoke_stdio.py # Windows: .venv\Scripts\python; MCP サーバーを stdio で起動して実際に呼ぶsmoke_stdio.py は仮想環境のインタプリタで実行してください。素の python ではありません。
サーバーの操作に mcp パッケージを使うため、それが入っていないシステム Python では
ModuleNotFoundError: No module named 'mcp' で落ちます。
CI は Linux と Windows の両方で、Python 3.10 と 3.12 に対してこれらを実行します。
テストは正常系よりも異常系に厚く書いてあります。この種のツールでは、壊れ方こそが本題だからです。
破損状態での fail open — 読めないデータベース、ディレクトリがあるべき場所にファイルがある状態、標準入力に流し込まれたゴミ、オブジェクトではなく JSON 配列。すべてのケースで操作は通らなければなりません。
「書き込まないこと」の証明 — 読み取り専用の要素については、全テーブルの行数を前後で記録して一致を検査します。監査対象を書き換える監査ツールには価値がありません。
非 ASCII 文字のサブプロセス往復 — 記録される理由は英語でないことが多く、Windows のコンソールコードページはそれを表現できません。これは実際に起きたバグでした。
json.dumpsが非 ASCII をエスケープして問題を隠しており、stderr への出力を平文に変えた瞬間に露出しました。標準入力での固まり — 開いたまま閉じられていない標準入力パイプを与えてサブプロセスを起動し、速やかに終了することを検査します。
現状と適用範囲
日常的に使っている実働ツールであり、フレームワークではありません。意図的に小さく作ってあります。SQLite と標準ライブラリのみ、1 つの関心事につき 1 ファイル、プラグイン機構なし。
Claude Code のフックを対象にしていますが、MCP サーバー側は任意の MCP クライアントで動きます。
既知の制約を、影響の大きい順に挙げます。
目標ゲートに「待機」の概念がない。 「バックグラウンド処理の完了を待っている」と「早々に諦めた」を区別できないため、待機がターン予算を消費します。現状の回避策は
extendです。stop-gateの同時実行が直列化されていない。 状態ファイルはロックなしの read-modify-write です。単一セッションでの利用 (これが唯一のサポート対象です) では発生しません。注入されるテキストは日本語で固定、切り替え不可。
session_brief.pyのブリーフィングとledger_session_reportMCP ツールは日本語がハードコードされています。詳細は上の「出力言語について」を参照してください。今のところNAGI_LANGのような切り替えはありません。
ライセンス
MIT — LICENSE を参照してください。
Available Tools
8 toolsledger_check_approachesARead-onlyIdempotent
Call this BEFORE retrying or re-planning a task. Never re-attempt an approach listed in dead_ends or no_gos unless you have new information that invalidates its reason.
Args: task (str): The exact task string used with ledger_log_approach.
Returns: dict: { "task": str, "dead_ends": [{"approach": str, "reason": str, "ts": str}, ...], "no_gos": [{"approach": str, "reason": str, "ts": str}, ...], "works": [{"approach": str, "reason": str, "ts": str}, ...], "total": int } Each list is ordered newest first. Empty lists when nothing has been recorded for the task.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds meaningful behavioral context: the return format (lists of approaches, reasons, timestamps, ordered newest first), empty-list behavior, and the policy against re-attempting failed approaches. This goes well beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded: the main usage instruction appears in the first sentence, followed by a clear Args/Returns breakdown. Every sentence is necessary and informative, with no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's single parameter, existing annotations, and the included output schema, the description is fully complete. It covers when to use, what the parameter means, the return structure with ordering and empty-list handling, and the behavioral policy—all an agent needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only defines 'task' as a string, but the description adds crucial meaning: 'The exact task string used with ledger_log_approach.' This clarifies the parameter's provenance and required exact match, significantly enhancing the schema's bare type definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to check known approaches (dead_ends, no_gos, works) for a task before retrying or re-planning. It distinguishes itself from sibling logging tools by being a read/check operation, and the specific verb 'check' plus resource 'approaches' makes it unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs when to use the tool: 'Call this BEFORE retrying or re-planning a task.' It also provides a clear exclusion rule: never re-attempt an approach listed in dead_ends or no_gos unless new information invalidates the reason. This is direct, actionable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ledger_log_actionA
Record a single autonomous action taken during a self-directed dev loop.
Use this to log any action the agent takes on its own initiative, tagged with a tier indicating how consequential it was.
Args: tier (int): Impact tier. Must be 0 (routine/info), 1 (notable), or 2 (high-impact, e.g. irreversible or user-facing). category (str): Short category label, e.g. "refactor", "deploy", "file_write", "dependency_change". Must be non-empty. description (str): Human-readable description of what was done. Must be non-empty. project (Optional[str]): Project/repo name this action belongs to.
Returns: dict: {"id": int} — the new action's row id.
Errors: Raises ValueError if tier is not in {0,1,2} or category/description are empty, with a message explaining the valid values.
| Name | Required | Description | Default |
|---|---|---|---|
| tier | Yes | ||
| project | No | ||
| category | Yes | ||
| description | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses return value format (id int), error behavior (ValueError for invalid tier and empty strings), and tier semantics. These details go beyond what annotations provide, offering actionable behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a one-sentence summary, then organized into Args, Returns, and Errors sections. It is concise, well-structured, and every sentence adds useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's modest complexity, the presence of an output schema, and annotations, the description fully covers purpose, parameters, return value, and error cases. It is complete enough for safe and correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema only provides types, while description adds allowed tier values (0,1,2), example categories, non-empty constraints, and optionality of project. This significantly enriches parameter understanding, especially with 0% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it records a single autonomous action in a dev loop, with a specific verb and object. It distinguishes from sibling tools by specifying 'autonomous action' rather than dispatch or verdict, giving it a distinct purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context for when to use: logging any action the agent takes on its own initiative, tagged with a tier. It does not explicitly exclude other ledger tools, but the context is sufficient for an agent to choose this among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ledger_log_approachA
Record the outcome of an approach tried (or considered) for a task.
Record every failed approach IMMEDIATELY after it fails, and every deliberate NO-GO decision, so future attempts (by you or another agent) skip them instead of re-discovering the same dead end.
Args: task (str): Stable identifier/description of the task. Use the SAME string across approaches to the same underlying task so ledger_check_approaches can find them. approach (str): Short description of the specific approach tried or considered. Must be non-empty. outcome (str): One of "DEAD_END" (tried and failed), "NO_GO" (decided against without trying), or "WORKS" (confirmed working). reason (str): Why the approach failed, was rejected, or worked. Must be non-empty.
Returns: dict: {"id": int} — the new approach record's row id.
Errors: Raises ValueError if task/approach/reason are empty, or outcome is not one of DEAD_END/NO_GO/WORKS, with a message naming the valid values.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | ||
| reason | Yes | ||
| outcome | Yes | ||
| approach | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses return format ('dict: {"id": int}'), error behavior (ValueError with message naming valid values), and the critical stable-task-identifier requirement. It also enumerates outcome values with meanings. This provides significant operational context beyond the sparse annotation flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized with a strong opening sentence, then a practical usage note, and a well-formatted Args section. Each sentence provides necessary guidance with no filler. It is appropriately sized for a tool with four parameters and meaningful behavioral constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers when to use, what the parameters mean, what the return value is, and potential errors. The output schema already documents return structure, so the description need not repeat it. Sibling tools are mentioned via ledger_check_approaches, providing integration context. This is a complete, self-contained description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates. It explains task as a stable identifier to reuse across approaches, approach as a short non-empty description, outcome with the allowed enum and their implications, and reason as a required explanation. This is far more informative than the bare schema properties.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Record the outcome of an approach tried (or considered) for a task.' This clearly specifies the verb (record), resource (approach outcomes), and scope (per task). It also distinguishes itself from siblings by referencing ledger_check_approaches as a companion and focusing specifically on approaches rather than actions or dispatches.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'Record every failed approach IMMEDIATELY after it fails, and every deliberate NO-GO decision.' It explains the purpose (avoid re-discovering dead ends). However, it does not explicitly state when not to use this tool or name alternatives such as ledger_log_action, so it lacks formal exclusions but provides clear context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ledger_log_dispatchA
Record a subagent dispatch (e.g. via the Agent tool) for audit and retry tracking.
Call this every time a subagent is dispatched for a task, so retries of the same task can be counted and budget-limited via ledger_task_status.
Args: task (str): Stable identifier/description of the task being dispatched. Use the SAME string across retries of the same underlying task so retry counting works. agent_type (str): Subagent type used (e.g. "fork", "general-purpose"). model (str): Model used for the dispatch (e.g. "sonnet", "opus"). brief_summary (str): One-line summary of what the dispatch was asked to do.
Returns: dict: {"id": int, "retry_count": int} where retry_count is the number of PRIOR dispatches recorded under the same task (0 for the first).
Errors: Raises ValueError if any field is empty.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | ||
| model | Yes | ||
| agent_type | Yes | ||
| brief_summary | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations indicate a write operation (readOnlyHint=false) but the description adds significant behavioral detail: the return dict with id and retry_count (and that retry_count counts PRIOR dispatches), the ValueError on empty fields, and the requirement to reuse the same task string. These details go beyond what annotations reveal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized into purpose, usage, Args, Returns, and Errors sections. Every sentence adds value; there is no padding, and the structure makes it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description accounts for usage, parameters, return value, and error handling. Given the tool's simple functionality and the explicit return/error details, the description is fully complete for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by providing meaningful definitions for each parameter: task (stable identifier, same string across retries), agent_type, model, and brief_summary, including examples for each.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Record') and resource ('a subagent dispatch'), explicitly stating its audit and retry tracking purpose. This clearly distinguishes it from sibling tools like ledger_log_action and ledger_log_verdict.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states to call it 'every time a subagent is dispatched', establishing a clear usage context. It also ties to ledger_task_status for retry counting but does not explicitly name alternative tools for non-dispatch logging, so it stops short of full when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ledger_log_verdictAIdempotent
Attach a verification verdict to a previously logged dispatch.
Use this after independently verifying a subagent's work, to record whether its claims were confirmed, refuted, or partially true.
Args: dispatch_id (int): The id returned by ledger_log_dispatch for the dispatch being verified. verdict (str): One of "CONFIRMED", "REFUTED", "PARTIAL". notes (Optional[str]): Optional free-text notes on the verification.
Returns: dict: {"ok": true, "task": str} — the task string of the dispatch the verdict was attached to.
Errors: Raises ValueError with an actionable message if dispatch_id does not exist, or if verdict is not one of the three allowed values.
| Name | Required | Description | Default |
|---|---|---|---|
| notes | No | ||
| verdict | Yes | ||
| dispatch_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare idempotentHint=true, destructiveHint=false, and readOnlyHint=false. The description adds valuable behavior beyond annotations: it returns a dict with 'ok' and 'task', and raises ValueError for invalid dispatch_id or verdict. It does not contradict annotations, and the idempotent hint is neither repeated nor undermined.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear one-sentence summary followed by Args, Returns, and Errors sections. It is concise for the amount of information it conveys; every sentence adds value, including error behavior and the return shape.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, the description is complete: it covers when to use it, all parameters, allowed values, return value, and error cases. The relationship to ledger_log_dispatch is explicit, making the tool's context within the ledger family clear. An output schema exists, but the description's Returns section still adds value by specifying the exact keys.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates fully with an Args section that explains each parameter. It even lists the exact allowed values for 'verdict' ('CONFIRMED', 'REFUTED', 'PARTIAL') which the schema does not provide as an enum. It also clarifies that 'notes' is optional and that dispatch_id comes from ledger_log_dispatch.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Attach a verification verdict to a previously logged dispatch.' It clearly distinguishes this from siblings like ledger_log_dispatch (which logs the initial dispatch) and ledger_log_approach (which logs an approach). The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use this after independently verifying a subagent's work.' It also references ledger_log_dispatch as the source of dispatch_id, establishing a clear prerequisite. It does not name alternative tools or explicit when-not scenarios, but the usage context is clear enough to avoid confusion with siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ledger_session_reportARead-onlyIdempotent
Generate a markdown report of actions and dispatches from the last N hours.
Actions are grouped by category; dispatches are listed with their resolved verdict or PENDING if not yet verified. Useful for a human-readable audit summary of recent autonomous activity.
Args: since_hours (int): How many hours back to include. Defaults to 24.
Returns: str: Markdown report, or a short "no entries" message if nothing was logged in the window.
| Name | Required | Description | Default |
|---|---|---|---|
| since_hours | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive behavior. The description adds valuable context: actions grouped by category, dispatches show resolved verdict or PENDING, and a 'no entries' message for empty windows. No contradictions exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized and front-loaded with the core purpose. It then provides digestible details on content, parameters, and return value, with every sentence adding value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter, no nested objects, read-only), the description fully covers behavior, output format, and edge cases. The presence of an output schema is noted, and the description's return explanation is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only provides the type and default for since_hours, with no description. The description explicitly explains that it is 'How many hours back to include' and states the default, fully compensating for the schema's lack of documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool generates a markdown report of actions and dispatches within a time window, with explicit grouping and verdict details. This clearly distinguishes it from sibling tools that log actions, dispatches, verdicts, or provide stats.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states it is 'useful for a human-readable audit summary', which clearly conveys when to use it. However, it does not explicitly mention alternatives or when not to use it, though sibling tool names imply other purposes like logging or stats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ledger_statsARead-onlyIdempotent
Aggregate statistics over actions and dispatches from the last N days.
Args: days (int): How many days back to include. Defaults to 7.
Returns: dict: { "actions_by_tier": {"0": int, "1": int, "2": int}, "actions_by_category": {category: int, ...}, "dispatch_count": int, "verdicts": {"CONFIRMED": int, "REFUTED": int, "PARTIAL": int, "PENDING": int} }
| Name | Required | Description | Default |
|---|---|---|---|
| days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is clear. The description adds behavioral context by explaining the aggregation scope (actions and dispatches over N days) and the exact return structure, which goes beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured, with clear 'Args' and 'Returns' sections. It front-loads the primary purpose and then delivers essential parameter and return information without any filler words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a read-only aggregation tool: it specifies the parameter, default value, and full return dictionary with keys and types. The presence of an output schema and clear annotations further round out the context, making the tool self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema parameter 'days' has no description in the schema, but the tool description fully compensates by stating 'How many days back to include. Defaults to 7.' This adds clear semantic meaning and default behavior beyond the bare schema definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Aggregate statistics over actions and dispatches from the last N days.' This is a specific verb+resource combination that clearly distinguishes it from sibling logging tools like ledger_log_action or ledger_log_dispatch, which are write operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for reading summary statistics rather than logging individual actions, providing clear context for when it would be used. It does not explicitly mention alternatives or exclusions, but the contrast with sibling tools is evident from the tool's aggregating purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ledger_task_statusARead-onlyIdempotent
Look up dispatch/retry/verdict status for a given task string.
Use this BEFORE dispatching a subagent to check whether the same task has already been retried too many times (budget enforcement).
Args: task (str): The exact task string used with ledger_log_dispatch.
Returns: dict: { "dispatch_count": int, # total dispatches recorded for this task "retry_count": int, # dispatch_count - 1, floored at 0 "last_verdict": str | None, # verdict of most recent dispatch, or null "over_retry_limit": bool # true when retry_count >= 2 }
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is covered. The description adds meaningful behavioral context beyond annotations: the exact return fields, the formula for retry_count (dispatch_count - 1 floored at 0), and the threshold for over_retry_limit (>= 2). This specifies the tool's semantics without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured with separate sections for Args and Returns. Every line serves a purpose: the first line states the function, the second provides usage context, and the return block details the output. No fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully specifies the tool's behavior, return values with types and comments, and the exact context for use. Since there is no separate output schema, the 'Returns' section compensates by documenting all four fields and their meanings. The tool is simple (one param, no nested objects) and the description covers all necessary aspects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% in the input schema (task has only type/title). The description compensates fully: 'task (str): The exact task string used with ledger_log_dispatch.' This adds crucial semantic meaning—that the string must match previously logged dispatches—which the schema alone could not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with 'Look up dispatch/retry/verdict status for a given task string,' which is a specific verb+resource phrase. It clearly distinguishes from sibling tools like ledger_log_dispatch (which logs) and ledger_stats (which aggregates). The additional 'Use this BEFORE dispatching a subagent' context further specifies its role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Use this BEFORE dispatching a subagent to check whether the same task has already been retried too many times (budget enforcement).' It also references ledger_log_dispatch for task string consistency. However, it does not enumerate when not to use or alternative tools, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
8 tool updates
v0.1.0- First observed
ledger_check_approaches - First observed
ledger_log_action - First observed
ledger_log_approach - First observed
ledger_log_dispatch - First observed
ledger_log_verdict - First observed
ledger_session_report - First observed
ledger_stats - First observed
ledger_task_status
TDQS
Each tool targets a distinct domain object: general actions, subagent dispatches, verdicts, task status, and approaches. No two tools perform the same function, and the descriptions make the boundaries clear, even where overlap might occur (e.g., log_action vs log_approach).
The consistent 'ledger_' prefix is good, but the suffix pattern is mixed: some tools use verb_noun (log_action, log_dispatch, log_verdict, log_approach, check_approaches) while others use noun_noun (task_status, session_report) or a bare noun (stats). This inconsistency makes the set slightly less predictable.
Eight tools is well within the ideal range for a specialized audit ledger. The set includes both write and query operations without unnecessary redundancy or bloat, and each tool earns its place.
The surface provides comprehensive coverage for the domain: writing actions, dispatches, verdicts, and approaches, plus reading and aggregating that data. There are no obvious gaps; the append-only nature of the ledger is appropriate and fully supported.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Guarded MCP server for agent-readable business truth, provenance, readiness, and discovery.
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
111Official remote MCP server for Archivist AI TTRPG campaign memory: characters, sessions, and more.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceTamper-evident audit logging for AI agents. Append-only, hash-chained, optionally Ed25519-signed log. The MCP server lets an agent keep and verify a record of what it actually did.7MIT
- AlicenseAqualityBmaintenanceA read-only MCP server that exposes local coding-agent session logs as three tools for introspection of recent work, debugging tool failures, and tracking token usage and estimated cost without parsing log files.3MIT
- AlicenseNot gradedqualityAmaintenanceThis MCP server enables AI agents to manage artifacts across sessions by providing tools for searching, retrieving, and registering entries in a persistent ledger, ensuring consistency and traceability of agent outputs.MIT
- AlicenseNot gradedqualityCmaintenanceAn MCP server providing an append-only, hash-chained evidence ledger for agent actions, where every record is a tamper-evident receipt cryptographically bound to all prior records and persisted as human-readable JSONL local state. It exposes tools to append records, verify chain integrity (pinpointing tampering), query records by actor/action/target/time, and fetch ledger stats—with no update or delete capabilities by design.Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/namakoo-dev/nagi-ledger'
If you have feedback or need assistance with the MCP directory API, please join our Discord server