コンテンツにスキップ
HaneDOCSEN

アプリを作る

Agent を組み込む

Agent の定義の書き方、アプリから AgentRun を始めて結果を受け取る方法、外への操作の承認の扱い方を説明します。

このページでは、アプリに Agent を組み込む方法を説明します。Agent は定義に書いた目的・入力・ツール・出力の範囲で動き、外への操作は承認を通してから Hane が行います。考え方は Agent にあります。

apiVersion: agents/v1alpha1
kind: Agent
metadata:
name: vehicle-check
spec:
purpose: 登録番号から、車両の車種・車検の満了日・走行距離を車両台帳で調べて答える
examples:
- 架空 300 あ 10-02 の車検はいつまで?
input:
type: object
required: [vehicle]
properties:
vehicle: { type: string, title: 登録番号 }
driver: llm
instructions: |-
1. data.find_record を type Vehicle、key に入力の vehicle で呼ぶ。
2. 見つかったら values の model・inspection_expiry・odometer_km を submit_result に入れ、status は answered にする。
3. 見つからなければ request_human_help で担当に引き継ぎ、status を handed_over にする。
台帳にない値を作らない。
tools: [data.find_record, request_human_help]
handover:
assignment: fleet-desk
limits:
maxToolCalls: 4
maxSeconds: 60
output:
type: object
required: [status, vehicle]
properties:
status:
title: 結果
oneOf:
- { const: answered, title: 回答した }
- { const: handed_over, title: 担当に引き継いだ }
vehicle: { title: 登録番号, type: string }
model: { title: 車種, type: [string, "null"] }
inspection_expiry: { title: 車検の満了日, type: [string, "null"] }
odometer_km: { title: 走行距離(km), type: [integer, "null"] }
項目 中身
purpose・examples 何をする Agent か、どう頼むか。受付とチャットの Agent が、頼む Agent を選ぶときに使う
input 入力の JSON Schema。チャットで頼める Agent は入力を持つ
driver 動かし方。下の表
tools 呼んでよいツール。Tool Gateway が呼ぶたびに確かめる
limits ツールの呼出しの数(50 まで)、秒数(600 まで)、モデルのトークン
output 結果の JSON Schema。submit_result の値をこれで確かめる。title は画面の項目名になる
approval 外への操作の承認を回す割り当ての規則と、DeciderPolicy
handover request_human_help で作る Task の割り当ての規則
driver 動き方 提供状況
scripted script に書いた手順どおりにツールを呼ぶ 使える
llm モデルがツールを選ぶ。instructions が要る 使える
opencode CLI をサンドボックスで動かし、モデルは Model Gateway を通す プレビュー
codex・claude Codex CLI・Claude Code をサンドボックスで動かし、MCP の Tool Gateway でツールを呼ぶ プレビュー 手元の開発環境だけ

業務の判断(計算や照合)は Agent にさせず、計算の定義や Workflow に書きます。Agent は calculations.run などのツールでそれを呼び、値と値の状態はサーバーが決めます。

const run = await unwrap(
hane.POST("/v1/agents/runs", { body: { agent: "vehicle-check", input: { vehicle: "架空 300 あ 10-02" } } }),
);
// run.status は queued。run.run_id で状態を読む

実行は非同期です。状態は queued → running → succeeded・failed・cancelled・limit_exceeded と進みます。終わったら、result に出力の Schema で確かめた結果が入ります。

async function waitRun(id: string) {
for (;;) {
const r = await unwrap(hane.GET("/v1/agents/runs/{id}", { params: { path: { id } } }));
if (r.status !== "queued" && r.status !== "running") return r;
await new Promise((ok) => setTimeout(ok, 2000));
}
}
const done = await waitRun(run.run_id);
console.log(done.status, done.result, done.trace.map((t) => `${t.kind} ${t.tool ?? ""} ${t.summary}`));
  • 画面に経過を出したいときは、組み込みチャット の会話を使うと、ツールの開始と終了・承認待ちを SSE で受け取れます。1 回の AgentRun だけを始める API には、経過を流す口はありません。
  • 自分のシステムで終わりを知りたいときは、webhook で agents.run.succeeded・agents.run.failed などを購読します(webhook)。
  • shadow: true を付けると、外への操作と人への引き継ぎをせず、記録だけを残します。定義を変える前の確かめに使えます。
  • 止めるときは POST /v1/agents/runs/{id}/cancel(本文は {})です。次のツールの呼出しから拒否されます。

頼む Agent が決まっていないときは、受付に自由な文を渡します。受付は有効な Agent の目的と頼み方の例から Agent を選び、入力の Schema に沿って文から値を拾います。

const r = await unwrap(hane.POST("/v1/agents/requests", { body: { messages: ["C-1001 の満了日を教えて"] } }));
if (r.outcome === "started") console.log(r.run?.run_id);
if (r.outcome === "needs_input") console.log(r.missing.map((m) => m.title)); // 聞き返す
if (r.outcome === "unmatched") console.log(r.candidates);

聞き返して答えをもらったら、messages の後ろに足して送り直します。

Agent がメール・SMS・電話・顧客の API への書込み・人が行う操作のツールを呼ぶと、Hane は宛先と内容を固定した ActionRequest を作り、digest を付けて、approval.assignment のグループに承認の Task を作ります。Agent は承認を待たずに結果を返し、送るのは承認の後に Hane が行います。

spec:
tools: [data.find_record, communication.send_email, request_human_help]
sender: fleet-desk # 送信の名義。管理者が承認するまで使えない
approval:
assignment: fleet-approval
decider: lease-application # 任意。金額などで決定者や段を決める DeciderPolicy

アプリでは、実行に結び付く ActionRequest を読んで状態を見せます。

const actions = await unwrap(hane.GET("/v1/agents/action-requests", { params: { query: { run_id: run.run_id } } }));
for (const a of actions.items) console.log(a.tool, a.state, a.parameters.contact?.masked, a.approval_task_id);

承認は、頼んだ人とは別の人が Task として決めます。決め方は データと Workflow を使う にあります。承認の前なら POST /v1/agents/action-requests/{id}/cancel で取り消せます。

郵送や窓口のように Hane の外で人が行う操作(human.perform)は、承認の後に実行の Task が担当に上がります。担当は承認された内容のとおりに行い、結果を POST /v1/agents/action-requests/{id}/perform で記録します。承認と違う内容は「受け付けられた」とは記録できず、逸脱として記録すると承認を取り直す Task になります。