Files
agent-bounty-protocol/apps/web/src/app/api/a2a/agents/connect/route.ts
OG T 436b092f3b
All checks were successful
CI and Production Smoke / smoke (push) Successful in 7s
feat: add external agent connect funnel
2026-06-12 01:06:25 +08:00

80 lines
3.1 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { buildAgentConnectDescription, connectExternalAgent } from "@/lib/a2a-agent-connect";
import { logA2aTrafficEvent } from "@/lib/a2a-traffic";
export const dynamic = "force-dynamic";
async function readConnectBody(request: NextRequest) {
const contentType = request.headers.get("content-type") || "";
if (contentType.includes("application/json")) {
const body = await request.json().catch(() => ({}));
return {
agentId: body.agent_id || body.agentId,
tool: body.tool || body.integration,
growthWebhook: body.growth_webhook || body.a2a_webhook || body.webhook,
walletAddress: body.wallet_address || body.wallet || body.payout_wallet,
campaign: body.campaign,
source: body.source,
channel: body.channel,
};
}
const formData = await request.formData().catch(() => null);
if (!formData) return {};
return {
agentId: formData.get("agent_id") || formData.get("agentId"),
tool: formData.get("tool") || formData.get("integration"),
growthWebhook: formData.get("growth_webhook") || formData.get("a2a_webhook") || formData.get("webhook"),
walletAddress: formData.get("wallet_address") || formData.get("wallet") || formData.get("payout_wallet"),
campaign: formData.get("campaign"),
source: formData.get("source"),
channel: formData.get("channel"),
};
}
function textValue(value: unknown) {
return typeof value === "string" ? value : "";
}
export async function GET() {
return NextResponse.json(buildAgentConnectDescription());
}
export async function POST(request: NextRequest) {
const input = await readConnectBody(request);
const result = await connectExternalAgent({
agentId: textValue(input.agentId),
tool: textValue(input.tool),
growthWebhook: textValue(input.growthWebhook),
walletAddress: textValue(input.walletAddress),
campaign: textValue(input.campaign),
source: textValue(input.source),
channel: textValue(input.channel),
});
await logA2aTrafficEvent({
headers: request.headers,
fallbackAgentId: result.success ? result.agent_id : textValue(input.agentId),
action: result.success ? "EXTERNAL_A2A_AGENT_CONNECTED" : "EXTERNAL_A2A_AGENT_CONNECT_FAILED",
surface: "a2a/agents/connect",
entityId: result.success ? `agent-connect:${result.agent_id}` : "agent-connect",
reason: result.success ? "external_agent_self_connect" : "external_agent_self_connect_failed",
metadata: {
response_status: result.success ? 200 : result.status,
response_summary: result.success ? "a2a_agent_connected" : result.error,
outbound_ready: result.success ? result.outbound_ready : false,
webhook_registered: result.success ? result.webhook_registered : false,
wallet_bound: result.success ? result.wallet_bound : false,
},
}).catch((error) => {
console.warn("[a2a/agents/connect] traffic audit failed", error);
});
if (!result.success) {
return NextResponse.json({ success: false, error: result.error }, { status: result.status });
}
return NextResponse.json(result);
}