カスタムエージェント
システムプロンプト + スキル + ツール + リスク上限 + トリガーをまとめた再利用可能なバンドル。CLI / REPL / HTTP / ワークフロー / cron から実行可能
🟢 構成可能: カスタムエージェントはレシピであり、別ランタイムではありません。 REPL セッションと同じエージェントループ、同じスキルレジストリ、 同じ資金確認ゲート上で動作します。
カスタムエージェント (Custom Agent) は次をまとめた保存済みバンドルです。
system_prompt(エージェントが実行時に従う指示)skill_idsのサブセット (ランナーが起動する DomainSkill)tool_names+tool_setsのサブセット (ランナーが公開するツール)risk_tier_maxの上限 (1 = 読み取り専用、4 = 手動のみ)。Web UI ウィザードでは「読み取り専用 / 資金移動なし / 資金移動可」の 3 択として提示され、最後の「資金移動可」は tier 3 (確認付き現物取引: swap、buy、sell) か tier 4 (永続・出金・autopilot を含む全資金操作) を選べます。定時・イベント実行のエージェントは資金移動ができず、資金移動は毎回確認が必要です。discovery_mode(ランナーが自己拡張できる積極性)triggersリスト (manual / cron / event)- 自由形式の
metadata
このバンドルは SQLite の agent_definitions テーブルに永続化されます。
実行経路は次のいずれかです。REPL /agents run、CLI minara agents run、
HTTP POST /v1/agents/:id/runs、Web UI の Run ドロワー、
ワークフローステップ agent_turn { agent_id }、cron / event トリガー。
カスタムエージェントは概念的に Anthropic の Managed Agents API ではなく Claude Code subagents に近い存在です。メインエージェントと同じプロセス内で ローカル実行され、同じスキルカタログを共有し、同じ安全境界を継承します。 サンドボックス化されたサードパーティランタイムではありません。
なぜオペレーターは欲しがるのか
- 再利用: 繰り返し発生するタスクを一度だけエンコードします。 「ETH 朝刊」「ポートフォリオ週次レビュー」「オンチェーン流入ウォッチャー」など、 それぞれを名前付きエージェントとして登録し、ワンクリックで起動できます。
- 限定されたツール面: リサーチ用エージェントには読み取り専用スキルだけで十分です
(
swap_tokensは不要)。財務エージェントには Hyperliquid 永続先物だけが必要です。 スキルセットが小さいほど、システムプロンプトはタイトに、無関係なツール呼び出しは少なく、 1 ターンあたりのトークンコストは低くなります。 - トリガー:
cron: "0 9 * * *"を付けたエージェントはオペレーター操作なしで 毎朝動きます。event: { event_name: "price.alert" }を付けたエージェントは イベントバスがマッチするイベントを発行したときに起動します。 - ワークフローから合成可能: 複数ステップのワークフローからは、
リサーチプロンプトをインライン化する代わりに
agent_turn { agent_id: "research-bot" }で参照できます。 ワークフロー作者がフローを持ち、エージェントが推論を持ちます。 - 共有可能:
~/.minara/agents/に JSON ファイルを置けば、 次回起動時にローダーが拾い上げます。research-botをチームメイトに エクスポートすると、相手のインスタンスはsource: "file:..."として読み込みます。
3 つの探索モード
discovery_mode は、実行時にランナーが skill_ids と tool_names
をどう扱うかを制御します。
新規エージェントの既定は free_discovery です。メインアシスタントと同じく、
エージェントは必要なスキルを自分で発見するため、Web UI ウィザードで事前に
選ぶ必要はありません。ツールは選択したスキルと risk_tier_max の上限から
決まるため、tool_names、tool_sets、discovery_skill_pool は
JSON ファイルローダーまたは HTTP API で設定する高度なフィールドであり、
ウィザードでは公開されません。
constrained
ハードなホワイトリストです。ランナーは宣言された skill_ids を厳密に起動し、
宣言された tool_names (および tool_sets の合併との交差) のみを公開します。
activate_skills メタツールは無効化されるため、LLM はターン中の自己拡張を行えません。
本番の信頼性を取りたい場合はこちらを選んでください。エージェントは毎回同じ形状で 走ります。レビューしやすく、テストしやすく、予算化しやすい構成です。
scenario_aware
後方互換のために残されており、現在の挙動は constrained と完全に同じです。
プロンプトごとにスキルをプリロードしていたシナリオ分類器は廃止されたため、
このモードは宣言された skill_ids だけを実行し、activate_skills は無効です。
既存のエージェントは値を保持しますが、新規エージェントは constrained を
選んでください。
free_discovery (既定)
宣言されたシードセットを起点に、LLM がターン中に activate_skills を
呼んでスキルを追加できます。
discovery_skill_pool の glob パターン (空 / 未指定ならカタログ全体) と
risk_tier_max によって制限されます。
慎重に使ってください。エージェントに解空間としてカタログ全体を渡す形になり、 オープンエンドなリサーチには強力ですが、狭く反復的なジョブには脆くなります。
3 モード共通の安全不変条件
risk_tier_maxは upsert 時だけでなく、トリガー時 にもランナーで強制されます。 たとえ DB を直接UPDATE agent_definitions SET risk_tier_max = 4で書き換えても、 cron / event / autopilot のトリガーでは実効上限が 2 にクランプされます。- 資金確認ゲートはエージェント実行のコンテキストを参照します。
テスト実行では、環境変数
MINARA_SKIP_FUND_CONFIRM=1が 設定されていても 2 段階確認を強制します。 - アーカイブ済みエージェントは fail-closed です。実行中の
agent_turnステップが アーカイブ済みエージェントを参照している場合、保存済みのスナップショットに対して 実行を継続しますが、アーカイブ済み id への新規実行は即座に失敗します。
トリガー
各エージェントには triggers リストがあります。v1 では 4 種類を提供します。
| 種類 | 形状 | 発火条件 |
|---|---|---|
manual | { kind: "manual" } | UI で Run をクリック / /agents run を入力 / POST /v1/agents/:id/runs |
cron | { kind: "cron", expr: "0 9 * * *", timezone?: "UTC" } | TriggerManager の tick が cron 式を跨ぐ |
event | { kind: "event", filter: { event_name: "price.alert", payload_match?: {...} } } | イベントバスがマッチするイベントを発行 |
once | { kind: "once", fire_at: 1717430400000 } | 実時刻が fire_at (unix ミリ秒) に達した時。一度だけ発火し、その後エージェントは自分をアーカイブします |
安全ルール: 既定では manual 以外のトリガーは upsert 時点で
risk_tier_max ≤ 2 を強制するため、定時 / イベントエージェントは資金を
移動できません。エージェントは自律的な資金移動を選択できます
(allow_autonomous_fund_moves: true。同じ書き込みに
confirm_autonomous_fund_moves: true が必要)。これにより非 manual の上限が
≤ 3 (確認付き現物取引) まで上がります。tier 4 (永続・出金・autopilot) は
常に手動トリガーが必要で、発火時には人がループに入ります。上限を超える
書き込みはストアが明確なエラーで拒否します。
once エージェントはリマインダーの実装そのものです。一度だけ発火し、その後
アーカイブされて二度と発火しません。発火済みのリマインダーを復元しても再生は
されません。再スケジュール (新しい fire_at を設定) するか、手動で実行して
ください。繰り返しのリマインダーには cron トリガーを使います。
通知
実行が終わると、Minara は 2 つの方法で知らせます。
アプリ内通知センター。 右上のベルが未読数と最近のエージェント実行の一覧を 表示し、各項目はその実行へのリンクになっています。常時オンでリアルタイムに 更新され、既読にしたりクリアしたりできる短い履歴を保持します。
ブラウザ通知。 設定 → 一般 (またはベルのクイックトグル) で「ブラウザ通知」を オンにすると、Minara のタブがバックグラウンドや最小化されているときに OS の デスクトップ通知を受け取れます。Minara のタブを見ているときは、代わりにアプリ内 メッセージとして表示されます。ブラウザは初回に許可を尋ねます。タブを閉じたり ブラウザを終了したりすると届かず、ページにはセキュアなコンテキスト (HTTPS) が 必要です。localhost は例外です。
どの実行が通知するか。 エージェントが自分で行う実行が通知します: 定時
(cron)、イベント (event)、一度きりのリマインダー、ワークフローのステップです。
自分で開始した実行 (Run ボタン、/agents run、チャットのターン) は、すでに
見ているので通知しません。テスト実行は通知しません。
エージェントごとの制御。 各エージェントには「アプリ内通知」設定があります。 うるさいエージェントではオフにしたり、失敗時だけ知らせるよう選べます。新しい エージェントは既定でオンです。
エージェントを参照するワークフロー
ワークフローの agent_turn ステップには 2 つの形があります。
// 推奨: 既存のカスタムエージェントを id で参照
{ "kind": "agent_turn", "agent_id": "research-bot",
"input": { "ticker": "ETH" } }
// レガシーなフォールバック: inline goal。エンジンは scoped な
// スキル / ツールサブセットを持たない一回限りのエージェントを立ち上げます
{ "kind": "agent_turn", "goal": "summarize recent ETH news" }agent_turn { agent_id } と tool_call の使い分け
推論、複数ツール探索、自然言語出力が必要なステップでは agent_turn を選びます。
リサーチ、起草、分類、要約などが該当します。
入力が決まっていて動作が確定している単一ステップでは tool_call を選びます。
1 回のスワップ、送金、残高チェック、価格取得などです。ツール呼び出しは
高速かつ低コストで、既存の資金確認ゲートをそのまま使えるため、
LLM ターンを跨いで確認コンテキストを再構築する必要がありません。
「ETH をショートしてから戦略ノートを書く」というワークフローは 2 ステップに分解します。
実行は tool_call { tool: "open_perps_position" }、
書き起こしは agent_turn { agent_id: "strategy-note" } です。
ローカルオートメーションスキルは、このマトリクスを自動的に守ります。
カスタムエージェントのカタログを公開し、「起草」「リサーチ」「要約」の意図は
agent_turn に、資金移動の意図は tool_call にルーティングします。
CLI
minara agents サブコマンドはフルライフサイクルを公開します。
| アクション | 形 | 用途 |
|---|---|---|
list | minara agents list [--archived] | 登録済みエージェントを一覧 |
get | minara agents get <id> | フル定義を JSON で出力 |
create | minara agents create --from <file.json> | JSON ファイルから挿入 |
update | minara agents update <id> --from <patch.json> | PATCH。意味のある変更で version を昇格 |
archive | minara agents archive <id> | ソフト削除。アタッチ済みトリガーを解除 |
run | minara agents run <id> [--input "..."] [--test] | アドホック実行を起動。イベントを stdout にストリーム |
export | minara agents export <id> | JSON を出力。ファイルへパイプ可能 |
import | minara agents import [--from <file.json>] | export の逆。--from 省略時は stdin を読む |
run はワークフローが完了 / 失敗するまで同期的にイベントストリームを開き、
最後に __adhoc__ の出力ペイロードを出します。cron / シェルスクリプトと
そのまま連携できます。
minara agents export research-bot > research-bot.json
scp research-bot.json bob@host:~/.minara/agents/
ssh bob@host minara agents list # research-bot が source=file:... で出現REPL
/agents スラッシュコマンドが対話版です。
| 形 | 振る舞い |
|---|---|
/agents または /agents list | 登録済みエージェントを一覧 |
/agents create | 対話的な collectArgs フロー: 名前 → システムプロンプト → スキル選択 |
/agents run [<id>] [<input>...] | エージェントを実行。<id> 省略時はライブピッカー |
/agents archive [<id>] | アーカイブ。<id> 省略時はライブピッカー。y/N で確認 |
/agents create フローは標準の
collectArgs
パターンに従います。必須フィールドを 1 つずつ尋ね、バリデーションに落ちたら
不正なフィールドだけを再質問し、空回答が 3 回続くとキャンセルされます。
Web UI
Web UI は AUTOMATE ナビゲーショングループ配下の /agents に
カスタムエージェントを表示します (Workflows と Autopilot と並びます)。
Web UI の /agents をご覧ください。
- 一覧ページ: 各エージェントを名前、リスク上限、discovery モード、 トリガー概要、カードごとの Run / Edit / Archive アクションを含むカードで表示。 Import ボタンは JSON ファイルアップロードを受け付け、New ボタンはウィザードを開きます。
- ウィザード (3 ステップ): ステップ 1 はスターターテンプレート選択 (researcher / treasury sentinel / drafting) または「空白」。 ステップ 2 で名前を付け、システムプロンプトを書き、スキルを選択します (ピッカーはハードホワイトリストモードでのみ表示)。ステップ 3 で discovery モード、 リスク上限、トリガー種別を選びます。安全クランプはインラインで表示されます。
- 詳細ページ: Overview / Definition / History の 3 タブ。
Definition タブはライブ JSON を表示し、PATCH 編集はアトミックに
versionを昇格させます。 - Run ドロワー: 一覧カードまたは詳細ページから開きます。
インライン SSE イベントストリームが
workflow:started→workflow:stepイベント → 終端のworkflow:completed/workflow:failedを表示します。Run as test (?test=1) はチェックボックスで、 テスト実行では env の skip 設定があっても資金確認モーダルが出ます。
REST エンドポイント
HTTP gateway は非 CLI 連携向けに同じ surface を公開します。
| メソッド | パス | 用途 |
|---|---|---|
GET | /v1/agents | 定義を一覧 (?archived=true でアーカイブ済みのみ) |
POST | /v1/agents | 作成。body は AgentDefinitionInput |
GET | /v1/agents/:id | 最新定義を取得 |
PATCH | /v1/agents/:id | 更新。body は部分 AgentUpdatePatch |
DELETE | /v1/agents/:id | アーカイブ (ソフト削除、復元可能) |
POST | /v1/agents/:id/restore | アーカイブ済みエージェントを復元 (トリガーを再装着) |
DELETE | /v1/agents/:id/permanent | 完全削除 (取り消し不可。実行履歴は残る) |
POST | /v1/agents/:id/runs | アドホック実行開始。?test=1 でテストモード |
GET | /v1/agents/:id/runs | 実行履歴 (ワークフローインスタンス履歴) |
GET | /v1/workflows/:id/instances/:iid/events/stream | 実行中インスタンス向け SSE イベントストリーム |
SSE エンドポイントは Web UI の Run ドロワーと同じものです。
イベントを単一の instance_id で透過的にフィルタリングします。
例: curl で作成
curl -X POST http://localhost:8080/v1/agents \
-H "Authorization: Bearer $GATEWAY_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d @research-bot.json
# アドホックなテスト実行を起動
curl -X POST "http://localhost:8080/v1/agents/research-bot/runs?test=1" \
-H "Authorization: Bearer $GATEWAY_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "input": "summarize recent ETH news" }'AgentDefinition JSON の例
{
"id": "research-bot",
"name": "Daily Research Bot",
"description": "Morning brief: trending tokens, macro context, watchlist signals.",
"system_prompt": "You are a markets research assistant. Output a 5-bullet brief covering crypto majors, US equities open, and any flagged watchlist alerts. No advice; observation only.",
"skill_ids": [
"analysis.market_overview",
"research.knowledge_base",
"minara.core"
],
"tool_names": ["get_price", "get_trending", "search_tokens"],
"tool_sets": ["market_data"],
"risk_tier_max": 1,
"discovery_mode": "constrained",
"triggers": [
{ "kind": "cron", "expr": "0 9 * * *", "timezone": "UTC" }
],
"metadata": {
"tags": ["research", "daily"],
"owner": "[email protected]"
}
}注意点:
- 読み取り専用の市場データのみを参照する cron トリガー付きエージェントには
risk_tier_max: 1(読み取り専用) が適しています。定時エージェントの上限は 既定で tier 2、allow_autonomous_fund_movesを設定すると tier 3 です。 その上限を超えると upsert が拒否されます。 discovery_mode: "constrained"は、ランナーがターン中にactivate_skillsを呼ばないことを意味します。スキル / ツール面は 宣言したとおりになります。tool_sets: ["market_data"]は、そのセット内の全ツールをtool_namesホワイトリストと合わせて追加します。ランナーは合併を取ります。
agent_turn { agent_id } を含むワークフロー JSON
{
"id": "morning-brief",
"name": "Morning Brief",
"version": 1,
"steps": [
{
"id": "step_1",
"kind": "tool_call",
"tool": "get_portfolio_snapshot",
"input": {}
},
{
"id": "step_2",
"kind": "agent_turn",
"agent_id": "research-bot",
"input": {
"portfolio_summary": "{{ steps.step_1.output }}"
}
},
{
"id": "step_3",
"kind": "tool_call",
"tool": "send_telegram",
"input": {
"text": "{{ steps.step_2.output }}"
}
}
]
}ワークフロー作者がフローを編成し、research-bot が推論を持ちます。
ステップ 2 が最初に実行されると、エンジンはエージェント定義を
workflow_instances.agent_def_snapshot にスナップショットします。
それ以降の research-bot への PATCH は、この実行中インスタンスに
影響しません。新規実行は新バージョンを取得します。
JSON ファイルによる共有
エージェントローダーは起動時に ~/.minara/agents/ (または
$MINARA_DATA_DIR/agents/) をスキャンします。AgentDefinition として
パースできる *.json ファイルは、source: "file:<絶対パス>" として
ストアに登録されます。
ファイル由来の行は PATCH ロック されています。REST / CLI からの更新は 明確なエラーで拒否されます。ディスク上のファイルを編集してから エージェントを再起動 (またはローダー同期エンドポイントを呼ぶ) してください。 これによりファイルが信頼の出所として保たれ、ディスクと DB の間で 静かなドリフトが発生しません。
ファイルを削除すると次回の同期で対応行がアーカイブされます。 そのため、ファイル削除によってそのエージェントを既にスナップショットしている ワークフローが壊れることはありません。
安全姿勢 (まとめ)
- ランタイムリスククランプ: 非 manual トリガー (cron / event / autopilot) は
effective_risk_tier_maxを 2 に、allow_autonomous_fund_moves設定時は 3 に クランプします。クランプは AgentRunner 内、LLM ターン直前、トリガー源の解決後に 実行されます。tier 4 ツールは自律ソースに対してレジストリゲートで常にブロックされます。 - コンテキストアウェアな資金確認: すべての資金移動ツール呼び出しは
資金確認ゲートを経由します。テスト実行では、ゲートは
MINARA_SKIP_FUND_CONFIRMに関係なく 2 段階確認を強制します。 テスト実行で資金が静かに動くことはありません。 - アーカイブエージェントの fail-closed: アーカイブ済みエージェントへの
手動実行は即座に失敗します。アーカイブ済みエージェントの cron トリガーは
3 回連続でスキップされると自動的に停止されます。実行中の
agent_turnステップは保存済みスナップショットに対して継続します。 アーカイブは未来方向のみの操作です。 - スナップショット分離:
agent_idでエージェントを参照する ワークフローインスタンスは、最初の実行時に定義全体をスナップショットします。 ソースエージェントへの後の PATCH や ARCHIVE は、実行中インスタンスに 影響しません。 - 監査ログ: 各実行は、要求されたリスク tier、実効 (クランプ済み)
リスク tier、トリガー源、ドロップされたスキル / ツールのリストを
監査ログに書き込みます。Web UI は History タブに表示し、CLI は
minara agents get <id>の後にインスタンスクエリで取得できます。
handler の契約は Fund-Moving Confirm を、 監査面全体は Audit & Overrides を参照してください。