Skip to content

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)。 詳細は 月次予算。