Discord エージェント構成¶
関連: Discord Bot / Gemini / アーキテクチャ / 月次予算
Discord 本体は、長い action 列挙ではなく Gemini Function calling で tool を選ばせる。
数字の正本は tool 実行結果(DB)である。
通知取込だけ、従来の JSON interpret を残している。
二系統の入口¶
flowchart LR
subgraph inputs [入口]
D[Discord 手動 / 画像]
M[メニュー文言]
N[Android 通知 ingest]
end
subgraph gemini [Gemini]
A["run_agent<br/>tools + 短い system"]
I["interpret<br/>JSON schema"]
end
subgraph exec [実行]
T[agent_tools.py]
V[discord_views.py]
DB[(PostgreSQL)]
end
D --> A
A -->|function call| T
T --> DB
T -->|display text| A
A -->|関西弁 reply + 表示| DiscordOut[Discord 返信]
M --> V
V --> DB
V -->|表 / リンク| DiscordOut
N --> I
I -->|action=create| DB
I --> Notify[チャンネル通知]
| 経路 | API | 役割 |
|---|---|---|
| Discord 会話 | GeminiClient.run_agent |
tool を自律選択。読む・書く・予算 |
| Discord メニュー | StatusMenuView |
利用状況・予算をボタンで表示(Gemini なし) |
| 通知 ingest | GeminiClient.interpret |
支出抽出の固定 JSON(後方互換) |
Discord 1 往復の流れ¶
sequenceDiagram
participant U as ユーザー
participant B as bot.py
participant G as Gemini
participant T as agent_tools
participant DB as PostgreSQL
U->>B: メッセージ / 画像
alt メニュー文言
B-->>U: ボタン付き案内
else 通常会話
B->>DB: 今月支出・収入・予算文脈
B->>G: run_agent(文脈 + tools)
loop 最大数ラウンド
G-->>B: function_call または最終テキスト
alt tool 呼び出し
B->>T: execute_tool
T->>DB: 参照 / 更新
T-->>B: JSON 結果 + display_chunks
B->>G: function_response
else テキスト完了
B-->>U: reply + display_chunks
end
end
end
Note over B: 保険: 残り / 内訳キーワードで<br/>tool 忘れを補完
モジュールの置き場¶
flowchart TB
subgraph src [src/finance_manager]
bot[bot.py<br/>受付・メニュー・保険]
views[discord_views.py<br/>ボタン]
gc[gemini_client.py<br/>run_agent / interpret]
at[agent_tools.py<br/>宣言と DB 実行]
bq[budget_queries.py<br/>残り・内訳の整形]
db[db.py]
tax[taxonomy.py]
end
bot --> views
bot --> gc
views --> bq
gc --> at
at --> bq
at --> db
at --> tax
bot --> bq
| ファイル | 責務 |
|---|---|
bot.py |
Discord イベント。文脈集め。tool 忘れのキーワード保険 |
gemini_client.py |
AGENT_SYSTEM_PROMPT + tool ループ。通知用 SYSTEM_PROMPT + schema |
agent_tools.py |
FunctionDeclaration と各 tool の実装 |
budget_queries.py |
【変動の残り】や内訳テキストの整形 |
tool 一覧(見た目の地図)¶
flowchart TB
Q[ユーザーの意図]
Q --> R[読む]
Q --> W[書く]
Q --> Bud[予算]
Q --> Extra[その他]
R --> get_budget_facts
R --> get_remaining
R --> get_tomorrow_guide
R --> get_budget_allotments
R --> get_month_breakdown
R --> get_period_spend
R --> get_surplus
R --> get_budget_summary
W --> create_expenses
W --> create_incomes
W --> update_expenses
W --> delete_expense
W --> update_income
W --> delete_income
Bud --> confirm_budget
Bud --> set_budget
Bud --> reopen_budget
Bud --> set_fixed_cost
Bud --> close_month
Extra --> create_wishlist
Extra --> create_planned_expense
使い分けの要点:
- 今日合計いくら / 欲しい指標を組み合わせたい →
get_budget_facts(metricsで必要な指標だけ指定) - 食費の今日残り / 週残り →
get_remaining(明細は出さない。食費のみ日割り表示) - 明日いくら使える / 明日の目安 →
get_tomorrow_guide(今日これ以上使わない前提。食費のみ日割り) - 週枠・月枠の確認 →
get_budget_allotments - 今月の内訳・一覧 →
get_month_breakdown(カテゴリ表+直近明細。全文は Grafana) - 昨日・先週・特定の日や範囲の使用額 →
get_period_spend(start_date/end_dateは両端を含むYYYY-MM-DD) - 支出を記録 →
create_expenses(金額の捏造禁止。同一メッセージで1回だけ) - 上限の訂正 / 枠変更 →
set_budget(確定済みでもceiling_yenを渡せる。未割当の別枠は載せ直す) - 確定取り消し →
reopen_budget(closedは不可)
画像の create_expenses は、Gemini が同じ内容を二度呼んだり、書き込み後のモデルフォールバックで再実行したりしないよう、同一 agent ターン内で指紋による重複スキップと write_done ガードを掛けている。
get_budget_facts の metrics に指定できる値: today_total_spent / today_category_spent / today_remaining / week_remaining / month_remaining / tomorrow_budget / week_budget / month_budget
全文の可視化: https://grafana.ntatsuya.com
新しい能力を足すときは、まず agent_tools.py に tool を1つ足す。
長い action 分岐や system 指示の増殖を避ける。
数字の正本¶
flowchart LR
M[モデルの口調]
T[tool の display_chunks]
H[bot のキーワード保険]
M -->|短い前置き| Out[Discord 返信]
T -->|金額・残り・明細| Out
H -->|tool 忘れ時のみ| Out
モデルは数字を作らない。
tool が DB から整形したテキストを display_chunks に載せ、run_agent が reply に連結する。
今日目安・週目安(再配分)¶
予算ガイドの計算は tool 表示の手前(budget_queries)で行う。
flowchart TD
L[カテゴリ月枠] --> W[週枠 = 週開始時点の月残り × 今週の日数 ÷ 週開始から月末までの日数]
W --> D{週に余裕?}
D -->|はい| D1[今日枠 = 週残り ÷ 今週の残り日数]
D -->|いいえ・超過済み| D2[今日枠 = 週枠 ÷ 今週の日数<br/>赤字は今日に載せない]
D1 --> Show[今日目安 = 今日枠 − 今日の使用]
D2 --> Show
W --> WeekShow[週目安 = 週枠 − 今週の使用]
週の余りは翌週へ持ち越す(月曜始まり)。頭打ちは無いので、使い控えた月は月末の枠が大きくなる。
【明日の目安】で明日が新しい週に入るときは、今週の使用を持ち込まない(week_spend_carried_to)。
詳細は 月次予算。