はじめに
こんにちは、普段は「Debugger」としてコードを書いているエンジニアです。
今回、完全ソロ開発で、DiscordとLINEから全ての雑務を効率化する、自分専用の自律型AIエージェント「Xeno(ゼノ)v1.0.0」を1ヶ月でビルドしました。
Qiitaのエンジニアの皆様に向けて、本プロダクトの裏側で冷徹に動いている「マルチプラットフォーム・ルーティング」、「1日3回のSandbox制限」、正式リリースに向けて実装した「menuコマンドによるサブスク隠蔽発火」のガチのバックエンド・ロジック(Pythonベース)をコード例とともに解説します。
1. コア・アーキテクチャと技術スタック
手軽さと裏側の堅牢性を担保するため、以下のスタックでパイプラインを構築しました。
言語: Python 3.11(高速なモックアップとAPI連携)/ 一部高速化モジュールにRustを並行採用
AI API: Gemini API(google-genai SDKによる構造化出力とコンテキスト処理)
インターフェース: LINE Messaging API / Discord.py
毎朝4時に起き、脳が一番冴えている4時間をフルに使って、Geminiとペアプログラミングをしながら設計を詰めました。
2. 【ガチ技術面】コアロジックの実装ブレイクダウン
① マルチプラットフォーム・ルーティングと初期化
LINEとDiscordという異なるデータ構造を持つWebhookを抽象化し、共通の「XenoCore」エージェントへルーティングする基盤ロジックです。
import os
from google import genai
from google.genai import types
class XenoAgent:
def __init__(self):
# Gemini APIの初期化(最新のSDK仕様に準拠)
self.client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
self.model_name = "gemini-2.5-flash" # 低遅延・高コンテキスト用
async def process_message(self, user_id: str, text: str, platform: str) -> str:
"""
プラットフォーム(LINE/Discord)に依存しない共通のメッセージ処理ロジック
"""
# 特殊コマンド(隠蔽されたサブスクロジック)のインターセプト
if text.strip().lower() == "menu":
return self._trigger_subscription_flow(user_id)
# 通常のAIエージェント思考処理
try:
response = self.client.models.generate_content(
model=self.model_name,
contents=text,
config=types.GenerateContentConfig(
system_instruction="あなたはユーザーの自律型AIエージェント Xeno です。全ての雑務を最速で処理してください。"
)
)
return response.text
except Exception as e:
return f"Xeno Core Error: {str(e)}"
def _trigger_subscription_flow(self, user_id: str) -> str:
# 表側には一切出さない、サブスク接続用の隠蔽URL発火ロジック
console_url = f"https://zdna-official.com/console?user={user_id}"
return (
f"Xeno Console initialized.\n"
f"本格的なフル機能の利用やサブスクリプション登録は、"
f"以下のリンクからコンソールへアクセスしてください。\n{console_url}"
)
② 1日3回のSandbox(体験版)制限マクロ
未登録ユーザーに対して、IPやユーザーIDベースで「1日3回まで」のメッセージ送信制限をかけるRedis等を用いたメモリキャッシュを想定したバリデーション・ロジックです。
```Python
import datetime
# 簡易的なインメモリ・キャッシュ(本番ではRedis等を推奨)
sandbox_cache = {}
def check_sandbox_limit(user_id: str) -> bool:
"""
体験版ユーザーの制限チェック(1日3回まで)
"""
today = datetime.date.today().isoformat()
if user_id not in sandbox_cache:
sandbox_cache[user_id] = {"date": today, "count": 0}
user_data = sandbox_cache[user_id]
# 日付が変わっていたらカウンターをリセット
if user_data["date"] != today:
user_data["date"] = today
user_data["count"] = 0
if user_data["count"] >= 3:
return False # 制限到達
user_data["count"] += 1
return True # 処理継続可能
```
これらをWebhookのエントリーポイントで以下のようにハンダ付けし、未登録ユーザーを安全に制限・誘導します。
```Python
# Webhook受信時の擬似コード
@app.post("/webhook/{platform}")
async def handle_webhook(platform: str, payload: dict):
user_id = extract_user_id(payload, platform)
user_message = extract_text(payload, platform)
# サブスク未登録かつ、3回の制限に引っかかった場合
if not is_subscribed(user_id) and not check_sandbox_limit(user_id):
return respond_to_platform(
platform,
"本日の体験版の試行回数(3回)が終了しました。本格利用は『menu』と送信してください。"
)
# コアロジックの実行
xeno = XenoAgent()
reply = await xeno.process_message(user_id, user_message, platform)
return respond_to_platform(platform, reply)
3. UI/UXにおける「引き算の技術」と条件分岐の最適化
今回の開発で得た最大の技術的知見は、「不必要なフロントエンドの実装をバックエンドの条件分岐に隠蔽する(パージする)」という設計思想です。
最初は画面上に「3ステップの使い方」や「サブスク画面へのリンク」などのUIコンポーネントを大量に実装していました。しかし、フロントエンドの情報過多はそのままユーザーの離脱率(バグ)に繋がります。
そこで、以下の引き算を行いました。
UIのパージ: フロントエンドはシアンブルー(#38BDF8)の「Connect」ボタンのみの2カラム・アシンメトリー構成(左寄せ)に極限までスリム化。
ロジックへの隠蔽: ユーザーへの使い方のアナウンスや、マネタイズ(サブスク)の動線は、上記の if text == "menu" というバックエンドのわずか数行の条件分岐コードにすべて処理を委ねました。
これにより、フロントエンドのコード量を劇的に減らしつつ、Twitter等のタイムラインでの訴求力を最大化させることに成功しました。
まとめ:AIと対話しながら「意思決定」をデバッグする
ソロ開発において、CursorやGeminiといったAIツールは非常に強力ですが、彼らはプロンプトに従ってコードを物質化する「ハンダゴテ」に過ぎません。
「このUIコンポーネントは本当に必要か?」「この例外処理のメッセージはユーザーに親切か?」という、仕様の引き算と設計の冷徹なジャッジ(デバッグ)は、人間にしかできません。
すべてのノイズをパージし、洗練されたバックエンドロジックを持つ『Xeno v1.0.0』の初陣です。