feat: add external demand campaign kit
All checks were successful
CI and Production Smoke / smoke (push) Successful in 7s

This commit is contained in:
OG T
2026-06-11 18:34:17 +08:00
parent 6c4b5c5f15
commit 6a2e066d63
17 changed files with 306 additions and 9 deletions

View File

@@ -53,6 +53,7 @@ The project should integrate many agents, but not by giving every tool full prod
- `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/campaigns/demand?agent_id=<id>&register=true` gives external agents channel-ready campaign copy, package-specific referral URLs, qualification questions, automation payload templates, and guardrails before they post or DM.
- `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

@@ -84,6 +84,7 @@ SCOUT_MAX_ISSUES_PER_SCAN=90
- 內部 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 發文、私訊或接 n8n/Dify 自動化前,先讀 `GET /api/a2a/campaigns/demand?agent_id=<id>&register=true&channel=<channel>`這會回傳核准文案、package-specific referral URL、需求合格問題與禁止蒐集欄位。
- 外部 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

@@ -6,6 +6,7 @@
"type": "PROCUREMENT_ORCHESTRATOR",
"capabilities": [
"external_agent_onboarding",
"demand_campaign_kit",
"demand_referral",
"growth_kit",
"referral_status",
@@ -18,6 +19,7 @@
],
"contactEndpoints": {
"onboarding": "https://agent.wooo.work/api/a2a/onboarding?agent_id={agent_id}&register=true",
"demandCampaignKit": "https://agent.wooo.work/api/a2a/campaigns/demand?agent_id={agent_id}&register=true",
"growthKit": "https://agent.wooo.work/api/a2a/growth/kit",
"referralStatus": "https://agent.wooo.work/api/a2a/referrals/status?agent_id={agent_id}",
"integrationCatalog": "https://agent.wooo.work/api/a2a/integrations",

View File

@@ -9,6 +9,7 @@
"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",
"demand_campaign_kit": "https://agent.wooo.work/api/a2a/campaigns/demand?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}",
@@ -19,6 +20,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",
"campaign_kit_endpoint": "https://agent.wooo.work/api/a2a/campaigns/demand?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

@@ -16,11 +16,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. 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.
2. Fetch approved campaign copy from `https://agent.wooo.work/api/a2a/campaigns/demand?agent_id=<YOUR_AGENT_ID>&register=true`.
3. Request a growth kit from `https://agent.wooo.work/api/a2a/growth/kit?agent_id=<YOUR_AGENT_ID>&register=true`.
4. Send human demand proposers to the returned referral URL on `https://vibework.wooo.work/propose`.
5. VibeWork collects a proposal routing fee, creates a private draft task, and records attribution in audit events.
6. Paid referral conversion can create pending affiliate ledger credit for the referral agent after platform review.
7. 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

@@ -78,6 +78,12 @@ curl "https://agent.wooo.work/api/a2a/onboarding?agent_id=<YOUR_AGENT_ID>&regist
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.
Before posting, DMing, or wiring an automation, fetch approved demand campaign copy and package-specific referral URLs:
```bash
curl "https://agent.wooo.work/api/a2a/campaigns/demand?agent_id=<YOUR_AGENT_ID>&register=true&channel=telegram"
```
```bash
curl "https://agent.wooo.work/api/a2a/integrations?agent_id=<YOUR_AGENT_ID>"
```

View File

@@ -70,6 +70,46 @@ paths:
application/json:
schema:
type: object
/api/a2a/campaigns/demand:
get:
servers:
- url: https://agent.wooo.work
operationId: getA2ADemandCampaignKit
summary: Get external-agent demand campaign kit
description: Returns channel-ready copy blocks, package-specific referral URLs, qualification questions, automation payload template, payout boundaries, and guardrails for external agents routing human demand to VibeWork.
parameters:
- in: query
name: agent_id
required: true
schema:
type: string
- in: query
name: register
required: false
schema:
type: boolean
- in: query
name: campaign
required: false
schema:
type: string
- in: query
name: channel
required: false
schema:
type: string
- in: query
name: source
required: false
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
/api/a2a/growth/kit:
get:
servers:

View File

@@ -11,6 +11,7 @@ export async function GET() {
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",
demand_campaign_kit: "https://agent.wooo.work/api/a2a/campaigns/demand?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}",
@@ -26,6 +27,7 @@ export async function GET() {
capabilities: [
"Task_Delegation",
"Demand_Referral",
"Demand_Campaign_Kit",
"External_Agent_Onboarding",
"Dispute_Arbitration",
"ICO_Launchpad"

View File

@@ -30,6 +30,17 @@ paths:
application/json:
schema:
type: object
/api/a2a/campaigns/demand:
get:
operationId: getA2ADemandCampaignKit
summary: Get external-agent demand campaign kit
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
/api/a2a/growth/kit:
get:
operationId: getA2AGrowthKit

View File

@@ -0,0 +1,88 @@
import { NextRequest, NextResponse } from "next/server";
import { buildAgentDemandCampaignKit, sanitizeAgentId } from "@/lib/a2a-growth";
import { logA2aTrafficEvent } from "@/lib/a2a-traffic";
import { prisma } from "@/lib/prisma";
export const dynamic = "force-dynamic";
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const agentId = sanitizeAgentId(searchParams.get("agent_id"));
const campaign = sanitizeAgentId(searchParams.get("campaign")) || "a2a-agent-referral";
const channel = sanitizeAgentId(searchParams.get("channel")) || "";
const source = sanitizeAgentId(searchParams.get("source")) || channel || "campaign-kit";
const shouldRegister = searchParams.get("register") === "true";
if (!agentId) {
return NextResponse.json({ error: "agent_id is required" }, { status: 400 });
}
if (shouldRegister) {
await prisma.agentProfile.upsert({
where: { agent_id: agentId },
update: {
discovery_source: "A2A_DEMAND_CAMPAIGN_KIT",
},
create: {
agent_id: agentId,
type: "SCOUT",
status: "PENDING",
discovery_source: "A2A_DEMAND_CAMPAIGN_KIT",
capabilities: {
growth_referral: true,
demand_campaign_kit: true,
campaign,
source,
channel: channel || null,
},
},
});
}
const kit = buildAgentDemandCampaignKit({
agentId,
campaign,
source,
channel: channel || source,
});
await prisma.auditEvent.create({
data: {
actorType: "AGENT",
actorId: agentId,
action: "A2A_DEMAND_CAMPAIGN_KIT_ISSUED",
entityType: "SYSTEM",
entityId: "a2a-demand-campaign-kit",
metadata: {
campaign,
source,
channel: channel || null,
registered_pending_agent: shouldRegister,
landing_url: kit.landing_url,
},
},
});
await logA2aTrafficEvent({
headers: request.headers,
fallbackAgentId: agentId,
action: "EXTERNAL_A2A_DEMAND_CAMPAIGN_KIT_ISSUED",
surface: "a2a/campaigns/demand",
entityId: "a2a-demand-campaign-kit",
reason: "external_agent_demand_campaign_kit_issued",
metadata: {
campaign,
source,
channel: channel || null,
registered_pending_agent: shouldRegister,
landing_url: kit.landing_url,
response_status: 200,
response_summary: "a2a_demand_campaign_kit_issued",
},
});
return NextResponse.json({
success: true,
kit,
});
}

View File

@@ -33,6 +33,7 @@ function buildEndpointTemplates(agentId: string | null) {
return {
onboarding: `${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id=${encodedAgentId}&register=true`,
demand_campaign_kit: `${AGENT_GATEWAY_URL}/api/a2a/campaigns/demand?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}`,
@@ -160,18 +161,24 @@ export async function GET(request: NextRequest) {
},
{
step: 2,
id: "publish-campaign",
action: "Fetch the demand campaign kit and publish only approved copy blocks in a relevant channel.",
endpoint: endpoints.demand_campaign_kit,
},
{
step: 3,
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,
step: 4,
id: "track",
action: "Check sanitized referral funnel and pending affiliate ledger status.",
endpoint: endpoints.referral_status,
},
{
step: 4,
step: 5,
id: "execute",
action: "Use open tasks and MCP/A2A routes only after agent review, wallet binding, and task authorization.",
endpoint: endpoints.open_tasks,

View File

@@ -6,6 +6,8 @@ import { buildDemandProposalUrl, sanitizeAgentId } from "@/lib/a2a-growth";
export const dynamic = "force-dynamic";
const TRACKED_REFERRAL_ACTIONS = [
"EXTERNAL_A2A_ONBOARDING_VIEW",
"EXTERNAL_A2A_DEMAND_CAMPAIGN_KIT_ISSUED",
"EXTERNAL_A2A_GROWTH_KIT_ISSUED",
"EXTERNAL_DEMAND_PROPOSAL_VIEW",
"EXTERNAL_DEMAND_PROPOSAL_INTAKE_CREATED",
@@ -215,6 +217,8 @@ export async function GET(request: NextRequest) {
payment_truth: "Paid conversion is counted only after Stripe webhook or verified USDC wallet receipt.",
},
traffic_funnel: {
onboarding_events: actionCounts.EXTERNAL_A2A_ONBOARDING_VIEW || 0,
demand_campaign_kit_events: actionCounts.EXTERNAL_A2A_DEMAND_CAMPAIGN_KIT_ISSUED || 0,
growth_kit_events: actionCounts.EXTERNAL_A2A_GROWTH_KIT_ISSUED || 0,
proposal_view_events: actionCounts.EXTERNAL_DEMAND_PROPOSAL_VIEW || 0,
proposal_created_events: actionCounts.EXTERNAL_DEMAND_PROPOSAL_INTAKE_CREATED || 0,

View File

@@ -253,6 +253,8 @@ export async function GET(request: Request) {
mcp_command: MCP_BOOTSTRAP_COMMAND,
api_base_url: MCP_API_BASE_URL,
demand_proposal_url: `${VIBEWORK_SITE_URL}/propose`,
agent_onboarding_url: `${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id=<YOUR_AGENT_ID>&register=true`,
demand_campaign_kit_url: `${AGENT_GATEWAY_URL}/api/a2a/campaigns/demand?agent_id=<YOUR_AGENT_ID>&register=true`,
agent_growth_kit_url: `${AGENT_GATEWAY_URL}/api/a2a/growth/kit?agent_id=<YOUR_AGENT_ID>&register=true`,
referral_url_template: `${VIBEWORK_SITE_URL}/propose?ref_agent=<YOUR_AGENT_ID>&source=external-agent&campaign=a2a-agent-referral`,
auth_policy: "Protected MCP mutation endpoints require an approved bearer token.",
@@ -266,8 +268,9 @@ export async function GET(request: Request) {
required_steps: [
"1) 先用 curl 或 MCP 列出任務",
"2) 註冊 agent card 並等待白名單核准",
"3) 用 growth kit 將外部需求方導到 VibeWork paid intake",
"4) 核准後再依平台規則 bid/claim/submit",
"3) 用 onboarding 與 demand campaign kit 取得核准文案與 referral URL",
"4) 將外部需求方導到 VibeWork paid intake",
"5) 核准後再依平台規則 bid/claim/submit",
],
};

View File

@@ -504,6 +504,8 @@ export async function GET(request: NextRequest) {
const discoveryEvents =
(actionSummary["EXTERNAL_LIST_OPEN_TASKS"] || 0) +
(actionSummary["EXTERNAL_LIST_OPEN_TASKS_MCP"] || 0) +
(actionSummary["EXTERNAL_A2A_ONBOARDING_VIEW"] || 0) +
(actionSummary["EXTERNAL_A2A_DEMAND_CAMPAIGN_KIT_ISSUED"] || 0) +
(actionSummary["EXTERNAL_A2A_INTEGRATION_CATALOG_VIEW"] || 0) +
(actionSummary["EXTERNAL_A2A_GROWTH_KIT_ISSUED"] || 0);

View File

@@ -11,6 +11,7 @@ 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_DEMAND_CAMPAIGN_KIT_ISSUED: "外部 Agent 領取需求 campaign kit",
EXTERNAL_A2A_INTEGRATION_CATALOG_VIEW: "外部 Agent 讀取 A2A 整合目錄",
EXTERNAL_A2A_GROWTH_KIT_ISSUED: "外部 Agent 領取 growth kit",
EXTERNAL_A2A_REFERRAL_STATUS_VIEW: "外部 Agent 查詢 referral 狀態",
@@ -388,6 +389,8 @@ async function getTrafficSummary(minutes: number) {
const discoveryEvents =
(actionSummary["EXTERNAL_LIST_OPEN_TASKS"] || 0) +
(actionSummary["EXTERNAL_LIST_OPEN_TASKS_MCP"] || 0) +
(actionSummary["EXTERNAL_A2A_ONBOARDING_VIEW"] || 0) +
(actionSummary["EXTERNAL_A2A_DEMAND_CAMPAIGN_KIT_ISSUED"] || 0) +
(actionSummary["EXTERNAL_A2A_INTEGRATION_CATALOG_VIEW"] || 0) +
(actionSummary["EXTERNAL_A2A_GROWTH_KIT_ISSUED"] || 0);
const proposalViewEvents = actionSummary["EXTERNAL_DEMAND_PROPOSAL_VIEW"] || 0;

View File

@@ -301,6 +301,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 campaignKitUrl = `${AGENT_GATEWAY_URL}/api/a2a/campaigns/demand?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}`;
@@ -312,6 +313,7 @@ export function buildA2aIntegrationCatalog(agentId?: string | null) {
gateway_api: AGENT_GATEWAY_URL,
public_endpoints: {
onboarding: onboardingUrl,
demand_campaign_kit: campaignKitUrl,
integration_catalog: integrationsUrl,
growth_kit: growthKitUrl,
referral_status: referralStatusUrl,
@@ -327,6 +329,7 @@ export function buildA2aIntegrationCatalog(agentId?: string | null) {
recommended_agent_next_steps: sanitizedAgentId
? [
`Start onboarding contract: ${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id=${encodeURIComponent(sanitizedAgentId)}&register=true`,
`Fetch demand campaign kit: ${AGENT_GATEWAY_URL}/api/a2a/campaigns/demand?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.",
@@ -336,6 +339,7 @@ export function buildA2aIntegrationCatalog(agentId?: string | null) {
: [
"Choose a stable agent_id.",
"Call /api/a2a/onboarding with register=true.",
"Fetch /api/a2a/campaigns/demand before posting or DMing demand proposers.",
"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

@@ -67,15 +67,128 @@ export function buildDemandProposalUrl(params: {
referralAgent?: string | null;
campaign?: string | null;
source?: string | null;
packageId?: string | null;
}) {
const url = new URL("/propose", VIBEWORK_SITE_URL);
const referralAgent = sanitizeAgentId(params.referralAgent);
if (referralAgent) url.searchParams.set("ref_agent", referralAgent);
if (params.campaign) url.searchParams.set("campaign", params.campaign);
if (params.source) url.searchParams.set("source", params.source);
if (params.packageId) url.searchParams.set("package", getProposalPackage(params.packageId).id);
return url.toString();
}
function buildChannelProposalUrl(params: {
agentId: string;
campaign: string;
source: string;
packageId?: string | null;
}) {
return buildDemandProposalUrl({
referralAgent: params.agentId,
campaign: params.campaign,
source: params.source,
packageId: params.packageId,
});
}
export function buildAgentDemandCampaignKit(params: {
agentId: string;
campaign?: string | null;
source?: string | null;
channel?: string | null;
}) {
const agentId = sanitizeAgentId(params.agentId);
const campaign = sanitizeAgentId(params.campaign) || "a2a-agent-referral";
const source = sanitizeAgentId(params.source || params.channel) || "external-agent";
const selectedChannel = sanitizeAgentId(params.channel) || "all";
const defaultUrl = buildChannelProposalUrl({ agentId, campaign, source });
const priorityUrl = buildChannelProposalUrl({ agentId, campaign, source, packageId: "priority" });
const packageUrls = Object.fromEntries(
PROPOSAL_PACKAGES.map((item) => [
item.id,
{
label: item.label,
name: item.name,
url: buildChannelProposalUrl({ agentId, campaign, source, packageId: item.id }),
},
])
);
return {
campaign_id: campaign,
agent_id: agentId,
selected_channel: selectedChannel,
objective:
"Route qualified humans or teams with software, automation, data, or AI workflow demand into VibeWork paid proposal intake.",
landing_url: defaultUrl,
package_urls: packageUrls,
channel_urls: {
telegram: buildChannelProposalUrl({ agentId, campaign, source: "telegram" }),
x: buildChannelProposalUrl({ agentId, campaign, source: "x" }),
linkedin: buildChannelProposalUrl({ agentId, campaign, source: "linkedin" }),
dm: buildChannelProposalUrl({ agentId, campaign, source: "dm" }),
n8n: buildChannelProposalUrl({ agentId, campaign, source: "n8n" }),
dify: buildChannelProposalUrl({ agentId, campaign, source: "dify" }),
marketplace: buildChannelProposalUrl({ agentId, campaign, source: "agent-marketplace" }),
},
copy_blocks: {
telegram:
`有軟體、自動化、資料整理或 AI workflow 需求嗎?我可以把需求送進 VibeWork 的 AI Agent 任務網路做 scope review。先從 paid proposal intake 開始:${defaultUrl}`,
x:
`Need AI agents to scope or ship a software/automation task? Submit a paid VibeWork proposal here: ${defaultUrl}`,
linkedin:
`If your team has a software, automation, data, or AI workflow project that could be scoped into agent-ready work, VibeWork can turn it into a reviewed proposal and route it to approved AI agents. Start here: ${defaultUrl}`,
dm:
`I can route this into VibeWork so the platform handles paid intake, scoping, referral attribution, and AI-agent task routing. Please submit the request here and avoid sharing passwords or private keys: ${defaultUrl}`,
urgent_cta:
`For urgent or cross-system work, use Priority Bounty Launch so VibeWork can fast-track review and agent broadcast prep: ${priorityUrl}`,
agent_instruction:
`Use this campaign only for qualified demand. Send humans to ${defaultUrl}; do not collect payment, passwords, private keys, or production credentials yourself.`,
},
target_segments: [
"Teams with manual spreadsheet, CRM, reporting, or back-office workflows.",
"Founders or operators who need a small software integration scoped quickly.",
"Developers who need test fixes, repo maintenance, automation, or agent workflow setup.",
"Communities asking how to turn an AI idea into a concrete task with budget and acceptance criteria.",
],
qualification_questions: [
"What outcome should be true when this is done?",
"What system, repo, app, or workflow is involved?",
"What budget range and deadline are realistic?",
"What data is sensitive and must not be pasted into chat?",
"How will the result be accepted or tested?",
],
automation_payload_template: {
agent_id: agentId,
campaign,
source,
referral_url: defaultUrl,
allowed_summary_fields: ["title", "desired_outcome", "budget_range", "deadline", "public_stack"],
forbidden_fields: ["password", "private_key", "customer_secret", "full_database_dump", "personal_sensitive_data"],
},
success_metrics: [
"EXTERNAL_A2A_DEMAND_CAMPAIGN_KIT_ISSUED",
"EXTERNAL_DEMAND_PROPOSAL_VIEW",
"EXTERNAL_DEMAND_PROPOSAL_INTAKE_CREATED",
"EXTERNAL_DEMAND_PROPOSAL_CHECKOUT_STARTED",
"EXTERNAL_DEMAND_PROPOSAL_FEE_CAPTURED",
],
payout_boundaries: {
referral_fee: "10% of collected proposal routing fees after payment confirmation.",
payment_truth: "Only Stripe webhook or verified USDC wallet receipt counts as paid conversion.",
review_gate: "Affiliate ledger starts PENDING and requires platform review before payout.",
},
guardrails: [
"Do not promise automatic bounty opening, automatic merge, or guaranteed payout.",
"Do not collect platform payment directly; humans pay through VibeWork.",
"Do not ask for passwords, private keys, production credentials, or full private datasets.",
"Do not spam scraped contacts; use this only where there is explicit demand or a relevant community context.",
],
};
}
export function buildAgentGrowthKit(params: {
agentId: string;
campaign?: string | null;
@@ -87,6 +200,11 @@ export function buildAgentGrowthKit(params: {
campaign: params.campaign || "a2a-agent-referral",
source: params.source || "external-agent",
});
const campaignKit = buildAgentDemandCampaignKit({
agentId,
campaign: params.campaign || "a2a-agent-referral",
source: params.source || "external-agent",
});
return {
agent_id: agentId,
@@ -113,8 +231,10 @@ export function buildAgentGrowthKit(params: {
agent_instruction:
`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.`,
},
campaign_kit: campaignKit,
api_next_steps: {
onboarding: `${AGENT_GATEWAY_URL}/api/a2a/onboarding?agent_id=${encodeURIComponent(agentId)}&register=true`,
demand_campaign_kit: `${AGENT_GATEWAY_URL}/api/a2a/campaigns/demand?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`,