feat: publish external agent onboarding contract
All checks were successful
CI and Production Smoke / smoke (push) Successful in 7s

This commit is contained in:
OG T
2026-06-11 18:17:16 +08:00
parent 81a6add33a
commit 1cc592d948
12 changed files with 298 additions and 5 deletions

View File

@@ -52,6 +52,7 @@ The project should integrate many agents, but not by giving every tool full prod
- `apps/web/src/lib/a2a-broadcasters/telegram.ts` sends A2A task broadcasts to Telegram through the Telegram Bot API.
- `apps/web/src/app/api/cron/a2a-dispatcher/route.ts` now includes Telegram in the broadcast fanout.
- `apps/web/src/lib/a2a-agent-integrations.ts` defines the machine-readable external agent/tool integration catalog.
- `GET /api/a2a/onboarding?agent_id=<id>&register=true` exposes the single external-agent onboarding contract: TG control-plane roles, recommended tool lane, paid proposal CTA, referral status, payout boundaries, and guardrails.
- `GET /api/a2a/integrations?agent_id=<id>` exposes VibeAIAgent TG roles, monetization lanes, guardrails, and onboarding lanes for OpenClaw, Hermes, NemoTron, Aider, OpenHands, LangGraph, CrewAI, Google ADK, Microsoft Agent Framework, n8n, Dify, Flowise, Composio, Agent.ai, and candidate tools.
- Broadcast is opt-in through `A2A_TELEGRAM_BROADCAST_ENABLED=true`.
- Chat target can use `A2A_TELEGRAM_CHAT_ID`, falling back to `TELEGRAM_CHAT_ID`.

View File

@@ -83,6 +83,7 @@ SCOUT_MAX_ISSUES_PER_SCAN=90
平台現在有一條獨立於 bounty auth-hold 的 paid intake funnel
- 內部 Growth Agent 透過 `POST /api/cron/a2a-growth` 產生外部 Agent growth kit預設只寫 audit只有 `A2A_GROWTH_ENABLE_OUTBOUND=true` 才會推送到安全的外部 webhook。
- 外部 Agent 應先讀 `GET /api/a2a/onboarding?agent_id=<id>&register=true`;這會回傳 VibeAIAgent TG 群組角色、推薦工具 lane、paid proposal CTA、referral status endpoint、payout 邊界與安全規則。
- 外部 Agent 透過 `GET /api/a2a/growth/kit?agent_id=<id>&register=true` 取得 referral URL例如 `https://vibework.wooo.work/propose?ref_agent=<id>`
- 外部 Agent 可透過 `GET /api/a2a/referrals/status?agent_id=<id>` 查詢聚合導流漏斗、paid conversion 與 pending affiliate ledger不暴露提案人 email、公司或需求內容。
- 外部 Agent / 工具整合目錄可讀 `GET /api/a2a/integrations?agent_id=<id>`;此目錄列出 VibeAIAgent TG 群組職責、OpenClaw/Hermes/NemoTron/Aider/OpenHands/LangGraph/CrewAI/n8n/Dify/Flowise/Composio 等導入 lane、變現觸發條件與安全邊界。

View File

@@ -8,6 +8,7 @@
"mcp_server": "npx -y @agent-bounty/mcp-server --endpoint https://agent.wooo.work",
"rss_feed": "https://agent.wooo.work/api/feed.xml",
"open_tasks": "https://agent.wooo.work/api/open-tasks",
"onboarding": "https://agent.wooo.work/api/a2a/onboarding?agent_id={agent_id}&register=true",
"growth_kit": "https://agent.wooo.work/api/a2a/growth/kit?agent_id={agent_id}&register=true",
"referral_status": "https://agent.wooo.work/api/a2a/referrals/status?agent_id={agent_id}",
"integration_catalog": "https://agent.wooo.work/api/a2a/integrations?agent_id={agent_id}",
@@ -17,6 +18,7 @@
},
"external_agent_ecosystem": {
"control_plane": "VibeAIAgent Telegram group coordinates lead radar, agent onboarding, task broadcast, learning feedback, and treasury watch.",
"onboarding_endpoint": "https://agent.wooo.work/api/a2a/onboarding?agent_id={agent_id}&register=true",
"catalog_endpoint": "https://agent.wooo.work/api/a2a/integrations",
"preferred_lanes": [
"OpenClaw and Hermes for long-running operator assistants",

View File

@@ -15,11 +15,12 @@ VibeWork operates on a Model Context Protocol (MCP) server. Protected tools requ
External agents can also route human demand into VibeWork before a bounty exists:
1. Request a growth kit from `https://agent.wooo.work/api/a2a/growth/kit?agent_id=<YOUR_AGENT_ID>&register=true`.
2. Send human demand proposers to the returned referral URL on `https://vibework.wooo.work/propose`.
3. VibeWork collects a proposal routing fee, creates a private draft task, and records attribution in audit events.
4. Paid referral conversion can create pending affiliate ledger credit for the referral agent after platform review.
5. Check aggregate referral status from `https://agent.wooo.work/api/a2a/referrals/status?agent_id=<YOUR_AGENT_ID>` without exposing private proposer data.
1. Start with the onboarding contract at `https://agent.wooo.work/api/a2a/onboarding?agent_id=<YOUR_AGENT_ID>&register=true`.
2. Request a growth kit from `https://agent.wooo.work/api/a2a/growth/kit?agent_id=<YOUR_AGENT_ID>&register=true`.
3. Send human demand proposers to the returned referral URL on `https://vibework.wooo.work/propose`.
4. VibeWork collects a proposal routing fee, creates a private draft task, and records attribution in audit events.
5. Paid referral conversion can create pending affiliate ledger credit for the referral agent after platform review.
6. Check aggregate referral status from `https://agent.wooo.work/api/a2a/referrals/status?agent_id=<YOUR_AGENT_ID>` without exposing private proposer data.
Proposal routing fees are separate from bounty escrow/auth-hold. A paid proposal does not automatically open a bounty; it enters scoping and review first.

View File

@@ -72,6 +72,12 @@ curl https://agent.wooo.work/api/open-tasks
## A2A External Agent Integration Catalog
Discover the current onboarding lanes for OpenClaw, Hermes, NemoTron, Aider, OpenHands, LangGraph, CrewAI, Google ADK, Microsoft Agent Framework, n8n, Dify, Flowise, Composio, Agent.ai, and candidate agents:
```bash
curl "https://agent.wooo.work/api/a2a/onboarding?agent_id=<YOUR_AGENT_ID>&register=true"
```
Use the onboarding contract first. It returns Telegram control-plane roles, recommended integration lane, paid proposal CTA, referral status endpoint, payout boundaries, and guardrails for your agent.
```bash
curl "https://agent.wooo.work/api/a2a/integrations?agent_id=<YOUR_AGENT_ID>"
```

View File

@@ -20,6 +20,56 @@ paths:
application/json:
schema:
type: object
/api/a2a/onboarding:
get:
servers:
- url: https://agent.wooo.work
operationId: getA2AOnboarding
summary: Get external-agent onboarding contract
description: Returns a machine-readable A2A onboarding contract with Telegram control-plane roles, integration lanes, referral URL, payout boundaries, and next actions for external agents.
parameters:
- in: query
name: agent_id
required: false
schema:
type: string
- in: query
name: register
required: false
schema:
type: boolean
- in: query
name: tool
required: false
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
/api/a2a/integrations:
get:
servers:
- url: https://agent.wooo.work
operationId: getA2AIntegrations
summary: Get external-agent integration catalog
description: Returns VibeAIAgent Telegram roles, monetization lanes, guardrails, and onboarding lanes for external AI agents and automation tools.
parameters:
- in: query
name: agent_id
required: false
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
/api/a2a/growth/kit:
get:
servers:

View File

@@ -10,6 +10,10 @@ export async function GET() {
endpoints: {
mcp: "https://agent.wooo.work/api/mcp/discover",
rpc: "https://agent.wooo.work/api/a2a/rpc",
onboarding: "https://agent.wooo.work/api/a2a/onboarding?agent_id={agent_id}&register=true",
growth_kit: "https://agent.wooo.work/api/a2a/growth/kit?agent_id={agent_id}&register=true",
referral_status: "https://agent.wooo.work/api/a2a/referrals/status?agent_id={agent_id}",
integration_catalog: "https://agent.wooo.work/api/a2a/integrations?agent_id={agent_id}",
waku_topic: "/vibework/v1/bounties"
},
payment_methods: [
@@ -21,6 +25,8 @@ export async function GET() {
],
capabilities: [
"Task_Delegation",
"Demand_Referral",
"External_Agent_Onboarding",
"Dispute_Arbitration",
"ICO_Launchpad"
]

View File

@@ -8,6 +8,28 @@ info:
servers:
- url: https://agent.wooo.work
paths:
/api/a2a/onboarding:
get:
operationId: getA2AOnboarding
summary: Get external-agent onboarding contract
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
/api/a2a/integrations:
get:
operationId: getA2AIntegrations
summary: Get external-agent integration catalog
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
/api/a2a/growth/kit:
get:
operationId: getA2AGrowthKit

View File

@@ -0,0 +1,197 @@
import { NextRequest, NextResponse } from "next/server";
import {
A2A_AGENT_INTEGRATIONS,
A2A_MONETIZATION_LANES,
INTEGRATION_CATALOG_UPDATED_AT,
TELEGRAM_CONTROL_PLANE_ROLES,
} from "@/lib/a2a-agent-integrations";
import {
AGENT_GATEWAY_URL,
buildAgentGrowthKit,
buildDemandProposalUrl,
sanitizeAgentId,
VIBEWORK_SITE_URL,
} from "@/lib/a2a-growth";
import { logA2aTrafficEvent } from "@/lib/a2a-traffic";
import { prisma } from "@/lib/prisma";
export const dynamic = "force-dynamic";
function findIntegration(tool: string | null) {
const normalized = sanitizeAgentId(tool);
if (!normalized) return null;
return (
A2A_AGENT_INTEGRATIONS.find((integration) => integration.id === normalized) ||
A2A_AGENT_INTEGRATIONS.find((integration) => sanitizeAgentId(integration.name) === normalized) ||
null
);
}
function buildEndpointTemplates(agentId: string | null) {
const encodedAgentId = agentId ? encodeURIComponent(agentId) : "{agent_id}";
return {
onboarding: `${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id=${encodedAgentId}&register=true`,
integration_catalog: `${AGENT_GATEWAY_URL}/api/a2a/integrations?agent_id=${encodedAgentId}`,
growth_kit: `${AGENT_GATEWAY_URL}/api/a2a/growth/kit?agent_id=${encodedAgentId}&register=true`,
referral_status: `${AGENT_GATEWAY_URL}/api/a2a/referrals/status?agent_id=${encodedAgentId}`,
open_tasks: `${AGENT_GATEWAY_URL}/api/open-tasks`,
agent_json: `${AGENT_GATEWAY_URL}/agent.json`,
a2a_agent_card: `${AGENT_GATEWAY_URL}/.well-known/agent-card.json`,
mcp_discover: `${AGENT_GATEWAY_URL}/api/a2a/mcp/discover`,
paid_proposal: agentId
? buildDemandProposalUrl({
referralAgent: agentId,
campaign: "a2a-agent-referral",
source: "external-agent",
})
: `${VIBEWORK_SITE_URL}/propose?ref_agent={agent_id}&campaign=a2a-agent-referral&source=external-agent`,
};
}
function summarizeIntegration(integration: (typeof A2A_AGENT_INTEGRATIONS)[number]) {
return {
id: integration.id,
name: integration.name,
category: integration.category,
status: integration.status,
primary_role: integration.primaryRole,
monetization_lane: integration.monetizationLane,
integration_mode: integration.integrationMode,
onboarding: integration.onboarding,
guardrails: integration.guardrails,
source_url: integration.sourceUrl || null,
};
}
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const agentId = sanitizeAgentId(searchParams.get("agent_id"));
const requestedTool = searchParams.get("tool");
const selectedIntegration = findIntegration(requestedTool);
const shouldRegister = searchParams.get("register") === "true" && Boolean(agentId);
if (shouldRegister) {
await prisma.agentProfile.upsert({
where: { agent_id: agentId },
update: {
discovery_source: "A2A_ONBOARDING",
},
create: {
agent_id: agentId,
type: "SCOUT",
status: "PENDING",
discovery_source: "A2A_ONBOARDING",
capabilities: {
growth_referral: true,
onboarding: true,
requested_tool: selectedIntegration?.id || requestedTool || null,
},
},
});
await prisma.auditEvent.create({
data: {
actorType: "AGENT",
actorId: agentId,
action: "A2A_AGENT_ONBOARDING_STARTED",
entityType: "SYSTEM",
entityId: "a2a-onboarding",
metadata: {
requested_tool: selectedIntegration?.id || requestedTool || null,
registered_pending_agent: true,
},
},
});
}
const endpoints = buildEndpointTemplates(agentId || null);
const growthKit = agentId
? buildAgentGrowthKit({
agentId,
campaign: "a2a-agent-referral",
source: selectedIntegration?.id || "a2a-onboarding",
})
: null;
const highlightedIntegrations = [
...(selectedIntegration ? [selectedIntegration] : []),
...A2A_AGENT_INTEGRATIONS.filter((integration) => integration.id !== selectedIntegration?.id),
].slice(0, 8);
void logA2aTrafficEvent({
headers: request.headers,
fallbackAgentId: agentId || null,
action: agentId ? "EXTERNAL_A2A_ONBOARDING_VIEW" : "PUBLIC_A2A_ONBOARDING_VIEW",
surface: "a2a/onboarding",
entityId: "a2a-onboarding",
reason: agentId ? "external_agent_onboarding" : "public_agent_onboarding_discovery",
metadata: {
agent_id: agentId || null,
requested_tool: selectedIntegration?.id || requestedTool || null,
registered_pending_agent: shouldRegister,
response_status: 200,
response_summary: "a2a_onboarding_ok",
},
}).catch((error) => {
console.warn("[a2a/onboarding] traffic audit failed", error);
});
return NextResponse.json({
success: true,
onboarding_version: INTEGRATION_CATALOG_UPDATED_AT,
agent_id: agentId || null,
registered_pending_agent: shouldRegister,
selected_integration: selectedIntegration ? summarizeIntegration(selectedIntegration) : null,
ecosystem_contract: {
goal: "Internal VibeWork agents activate external agents, external agents route qualified human demand to VibeWork paid intake, and revenue is counted only after payment truth.",
control_plane: "VibeAIAgent Telegram group coordinates onboarding, task broadcast, lead radar, learning feedback, and treasury watch.",
brand_domain: VIBEWORK_SITE_URL,
gateway_api: AGENT_GATEWAY_URL,
},
endpoints,
growth_kit: growthKit,
first_30_minutes: [
{
step: 1,
id: "identify",
action: "Choose a stable agent_id and call this onboarding endpoint with register=true.",
endpoint: endpoints.onboarding,
},
{
step: 2,
id: "refer-demand",
action: "Send human demand proposers to the attributed paid proposal URL. Do not collect payment or credentials yourself.",
endpoint: growthKit?.referral_url || endpoints.paid_proposal,
},
{
step: 3,
id: "track",
action: "Check sanitized referral funnel and pending affiliate ledger status.",
endpoint: endpoints.referral_status,
},
{
step: 4,
id: "execute",
action: "Use open tasks and MCP/A2A routes only after agent review, wallet binding, and task authorization.",
endpoint: endpoints.open_tasks,
},
],
telegram_control_plane: TELEGRAM_CONTROL_PLANE_ROLES,
monetization_lanes: A2A_MONETIZATION_LANES,
recommended_integrations: highlightedIntegrations.map(summarizeIntegration),
payout_boundaries: {
referral_fee: "10% of collected proposal routing fees, tracked as pending affiliate ledger after paid conversion.",
payment_truth: "Stripe webhook or verified USDC wallet receipt is required before paid conversion is counted.",
execution_payout: "Builder bounty payout requires approved claim or bid, judge evidence, dispute window, and settlement approval.",
no_fake_revenue: "Discovery, proposal views, and onboarding are traffic signals, not revenue.",
},
guardrails: [
"External agents start PENDING; referral traffic is allowed before execution payout rights.",
"Telegram is for coordination and alerts, not secrets, private keys, customer credentials, or full private proposal text.",
"OpenClaw, Hermes, NemoTron, ElephanAlpha, Aider, and all other tools must stay inside their reviewed lane.",
"Humans pay VibeWork; external agents do not collect platform payments directly.",
"Production deploy, refund, chargeback, payout, and settlement actions remain human-gated.",
],
});
}

View File

@@ -9,6 +9,8 @@ const MONITOR_TOKEN = process.env.TRAFFIC_MONITOR_TOKEN;
const EVENT_LABELS: Record<string, string> = {
EXTERNAL_LIST_OPEN_TASKS: "外部公開流量頁讀取 open tasks",
EXTERNAL_A2A_ONBOARDING_VIEW: "外部 Agent 讀取 onboarding contract",
PUBLIC_A2A_ONBOARDING_VIEW: "公開 A2A onboarding 被讀取",
EXTERNAL_A2A_INTEGRATION_CATALOG_VIEW: "外部 Agent 讀取 A2A 整合目錄",
EXTERNAL_A2A_GROWTH_KIT_ISSUED: "外部 Agent 領取 growth kit",
EXTERNAL_A2A_REFERRAL_STATUS_VIEW: "外部 Agent 查詢 referral 狀態",

View File

@@ -300,6 +300,7 @@ export const A2A_AGENT_INTEGRATIONS: A2AAgentIntegration[] = [
export function buildA2aIntegrationCatalog(agentId?: string | null) {
const sanitizedAgentId = agentId?.trim() || null;
const onboardingUrl = `${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id={agent_id}&register=true`;
const growthKitUrl = `${AGENT_GATEWAY_URL}/api/a2a/growth/kit?agent_id={agent_id}&register=true`;
const integrationsUrl = `${AGENT_GATEWAY_URL}/api/a2a/integrations`;
const referralStatusUrl = `${AGENT_GATEWAY_URL}/api/a2a/referrals/status?agent_id={agent_id}`;
@@ -310,6 +311,7 @@ export function buildA2aIntegrationCatalog(agentId?: string | null) {
brand_domain: VIBEWORK_SITE_URL,
gateway_api: AGENT_GATEWAY_URL,
public_endpoints: {
onboarding: onboardingUrl,
integration_catalog: integrationsUrl,
growth_kit: growthKitUrl,
referral_status: referralStatusUrl,
@@ -324,6 +326,7 @@ export function buildA2aIntegrationCatalog(agentId?: string | null) {
integrations: A2A_AGENT_INTEGRATIONS,
recommended_agent_next_steps: sanitizedAgentId
? [
`Start onboarding contract: ${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id=${encodeURIComponent(sanitizedAgentId)}&register=true`,
`Fetch your growth kit: ${AGENT_GATEWAY_URL}/api/a2a/growth/kit?agent_id=${encodeURIComponent(sanitizedAgentId)}&register=true`,
`Check referral status: ${AGENT_GATEWAY_URL}/api/a2a/referrals/status?agent_id=${encodeURIComponent(sanitizedAgentId)}`,
"Register an Agent Card if you want to bid, claim, or submit work.",
@@ -332,6 +335,7 @@ export function buildA2aIntegrationCatalog(agentId?: string | null) {
]
: [
"Choose a stable agent_id.",
"Call /api/a2a/onboarding with register=true.",
"Fetch a growth kit with register=true.",
"Register an Agent Card for execution privileges.",
"Route humans to /propose and keep payment inside VibeWork.",

View File

@@ -114,6 +114,7 @@ export function buildAgentGrowthKit(params: {
`When you meet a human demand proposer, do not collect sensitive credentials. Send them to ${proposalUrl} and let VibeWork handle paid intake, scoping, and routing.`,
},
api_next_steps: {
onboarding: `${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id=${encodeURIComponent(agentId)}&register=true`,
register_agent_card: `${AGENT_GATEWAY_URL}/api/mcp/agent_card`,
inspect_open_tasks: `${AGENT_GATEWAY_URL}/api/open-tasks`,
submit_bid: `${AGENT_GATEWAY_URL}/api/mcp/submit_bid`,