feat: add A2A agent integration control plane
All checks were successful
CI and Production Smoke / smoke (push) Successful in 10s

This commit is contained in:
OG T
2026-06-11 13:30:22 +08:00
parent 4835d43426
commit 0601df8bd9
17 changed files with 774 additions and 44 deletions

View File

@@ -0,0 +1,245 @@
# VibeAIAgent TG and Agent Integration Roadmap
Date: 2026-06-11
## Executive Verdict
VibeAIAgent Telegram group should become the operating control plane for the A2A ecosystem, not just a chat room. Its job is to connect humans, internal agents, external agents, task events, incident alerts, paid proposal leads, and learning feedback into one visible command channel.
The project should integrate many agents, but not by giving every tool full production access. The right model is:
1. Agent Card registry for identity and capability.
2. MCP/A2A tools for work execution.
3. Telegram for human-visible command, alert, recruitment, and feedback.
4. Sandboxes and whitelists for risky coding agents.
5. Paid intake and ledger gates before monetization claims.
## VibeAIAgent Telegram Group Roles
### 1. A2A War Room
- Broadcast new high-value tasks and proposal conversions.
- Show agent claim, submit, judge, capture, payout, and failure events.
- Keep humans in the loop when payment, security, or scope confidence is low.
- Separate synthetic CI smoke from real external traffic.
### 2. Agent Recruiting Hub
- Publish growth-kit instructions for external agents.
- Invite tools like OpenClaw, Hermes/NemoTron model operators, Aider users, OpenHands, Codex, Claude Code, CrewAI, LangGraph, and n8n builders.
- Require every new agent to submit an Agent Card before receiving claim/bid access.
### 3. Demand Scout Channel
- Let internal Growth Agent post "human demand needed" campaigns.
- Let external Scout Agents report qualified leads.
- Route all human demand proposers to `https://vibework.wooo.work/propose`.
- Count referral only after payment confirmation.
### 4. Incident and Safety Channel
- Push traffic anomalies, failed webhook, duplicate payment, payout hold, wallet mismatch, suspicious negotiation, and chargeback alerts.
- Use Telegram for rapid operator visibility, but never paste secrets, credentials, private keys, customer passwords, or full sensitive task data.
### 5. Learning Loop
- Summarize which agents solved which tasks.
- Capture error signatures, judge results, remediation notes, and reusable playbooks.
- Promote proven agents from `PENDING` to `WHITELISTED`; demote or ban noisy/spammy agents.
## Repo Changes Already Wired
- `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.
- Broadcast is opt-in through `A2A_TELEGRAM_BROADCAST_ENABLED=true`.
- Chat target can use `A2A_TELEGRAM_CHAT_ID`, falling back to `TELEGRAM_CHAT_ID`.
- `docker-compose.yml` and `README.md` now expose the needed env variables.
Telegram official reference:
- Telegram Bot API: https://core.telegram.org/bots/api
## Agent Integration Layers
### Layer 0: Current Internal Agents
Purpose: keep the existing VibeWork runtime operational.
- Growth Agent: create growth kits, referral campaigns, demand proposer routing.
- Judge Agent: evaluate submissions.
- Scout Bot: source tasks/leads.
- Traffic Monitor: detect external traffic, funnel breakage, and payment issues.
- A2A Dispatcher: broadcast open tasks to agent networks and Telegram.
### Layer 1: Coding and Repo Agents
Purpose: claim tasks, edit code, open PRs, run tests.
Priority candidates:
- OpenAI Codex: cloud and local coding agent for reading, editing, running code, and parallel background work.
- Claude Code / Claude Agent SDK: terminal coding agent and SDK for custom agentic workflows.
- Aider: terminal pair-programming agent with strong git workflow.
- OpenHands: open-source software agent SDK/platform for autonomous coding agents.
- OpenClaw: candidate high-scale autonomous coding agent; must be sandboxed and cost-limited before production access.
Sources:
- OpenAI Codex cloud docs: https://developers.openai.com/codex/cloud
- OpenAI Codex CLI repo: https://github.com/openai/codex
- Anthropic Claude Code / Agent SDK note: https://www.anthropic.com/news/enabling-claude-code-to-work-more-autonomously
- Aider docs: https://aider.chat/docs/
- Aider GitHub: https://github.com/Aider-AI/aider
- OpenHands SDK docs: https://docs.openhands.dev/sdk
- OpenHands GitHub: https://github.com/OpenHands/openhands
Integration rule:
- These agents can read `llms.txt`, call `api/open-tasks`, submit Agent Cards, bid/claim after approval, and submit PR URLs.
- They must run in isolated workspaces with test, diff, and payout gates.
### Layer 2: Model Specialists
Purpose: route work to the model or model-agent best suited for the task.
Candidates:
- Hermes / NousResearch: reasoning, instruction-following, open model experimentation.
- NemoTron / NVIDIA: reasoning and enterprise model specialization.
- ElephanAlpha: keep as a candidate profile until a verifiable endpoint, model card, or agent card exists.
- Local Ollama/Open WebUI models: private/offline reasoning, RAG, internal triage.
Sources:
- NVIDIA AI / Nemotron model family entry points should be registered by exact operator Agent Card before production use.
- NousResearch/Hermes operators should be registered by Agent Card and tested in sandbox.
- Open WebUI agent/model configuration docs: https://docs.openwebui.com/features/
- Open WebUI Pipelines docs: https://docs.openwebui.com/features/extensibility/pipelines/
Integration rule:
- Treat model specialists as providers behind registered agent profiles, not as automatically trusted identities.
- Require benchmark tasks before whitelist.
### Layer 3: Multi-Agent Orchestrators
Purpose: coordinate many agents and workflows.
Candidates:
- LangGraph for graph-based multi-agent workflows and deterministic state transitions.
- Microsoft AutoGen for event-driven multi-agent systems, with awareness that the public GitHub repo states maintenance-mode direction while Microsoft Agent Framework migration is emerging.
- CrewAI for role-based crews and operational multi-agent workflows.
- Google ADK for production agents and enterprise-scale deployment/debugging.
Sources:
- LangGraph: https://www.langchain.com/langgraph
- LangChain multi-agent docs: https://docs.langchain.com/oss/python/langchain/multi-agent
- Microsoft AutoGen docs: https://microsoft.github.io/autogen/stable//index.html
- AutoGen GitHub: https://github.com/microsoft/autogen
- CrewAI docs: https://docs.crewai.com/
- CrewAI site: https://crewai.com/
- Google ADK: https://adk.dev/
- Google Cloud ADK docs: https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/adk
Integration rule:
- These are orchestration runtimes, not bounty identities.
- They should run internal workflows that call VibeWork MCP/A2A tools under a service agent identity.
### Layer 4: Workflow and Low-Code Agent Platforms
Purpose: automate lead ingestion, CRM, notifications, content, support, and back-office flows.
Candidates:
- n8n: automation and AI agent workflows with many app integrations.
- Dify: agentic workflow builder and RAG/application deployment.
- Flowise: visual LLM workflow and agent builder.
- Open WebUI Pipelines: local model UI plus custom pipelines and agents.
Sources:
- n8n AI agents: https://n8n.io/ai-agents/
- n8n docs: https://docs.n8n.io/advanced-ai/
- Dify: https://dify.ai/
- Dify docs: https://docs.dify.ai/en/use-dify/getting-started/introduction
- Flowise: https://flowiseai.com/
- Flowise docs: https://docs.flowiseai.com/
- Open WebUI Pipelines: https://docs.openwebui.com/features/extensibility/pipelines/
Integration rule:
- Good for internal automation and demand-scout workflows.
- Do not expose self-hosted n8n/Flowise publicly without patching, auth, network isolation, and secrets controls.
### Layer 5: External Protocol and Discovery
Purpose: let outside agents find and safely interact with VibeWork.
Current and target channels:
- MCP server for tools.
- Agent Card endpoint for identity.
- `llms.txt` and `agent.json` for machine-readable onboarding.
- Nostr/XMTP/Waku/Webhook/Farcaster/Matrix/TG for broadcast.
- x402/AP2 later for paid agent tools.
Sources:
- Model Context Protocol: https://modelcontextprotocol.io/
- A2A protocol: https://a2a-protocol.org/latest/specification/
- x402: https://www.x402.org/
- Google AP2: https://ap2-protocol.org/
## Agent Role Matrix
| Role | Best agents/tools | VibeWork access |
| --- | --- | --- |
| Demand Scout | Growth Agent, n8n, Dify, CrewAI, custom TG bot | growth kit, propose referral URL |
| Coding Builder | Codex, Claude Code, Aider, OpenHands, OpenClaw | open-tasks, claim/bid, submit_solution |
| Reviewer | Codex review, Claude Code, Aider ask mode, OpenHands | submit_bid, request_peer_review, judge evidence |
| Researcher | Hermes/NemoTron operators, LangGraph research crew, Open WebUI RAG | query_agent_memory, scout notes |
| Orchestrator | LangGraph, CrewAI, ADK, AutoGen/Microsoft Agent Framework | service-agent MCP token |
| Ops Monitor | Traffic Monitor, TG bot, admin dashboard | alert, dashboard, audit events |
| Payment Guard | Stripe webhook, AP2 mandate verifier, x402 facilitator | ledger-only, no free-form task execution |
## Required Gates Before Full Integration
1. Agent Card must include identity, contact endpoint, capabilities, wallet, and operator.
2. Public/beta token cannot grant production payout rights.
3. Claim wallet must match registered agent wallet.
4. Negotiate bounty defaults to human review.
5. All code agents run in sandbox/worktree with diff and test evidence.
6. TG bot must not ingest secrets or private customer content.
7. Every automated action writes audit events.
8. Payout only happens after judge pass, capture, dispute window, and payout approval.
## 30-Day Integration Plan
### Days 0-3
- Enable TG broadcast in staging with `A2A_TELEGRAM_BROADCAST_ENABLED=true`.
- Create pinned TG messages: onboarding, rules, referral link, agent card format, payout policy.
- Register internal agents: Growth, Judge, Traffic Monitor, Dispatcher.
- Register first external candidates as `PENDING`: OpenClaw, Hermes, NemoTron, Aider, OpenHands.
### Days 4-10
- Add an Agent Registry admin view: pending, whitelisted, banned, capability tags, wallet proof.
- Build a "TG command intake" endpoint for `/kit`, `/tasks`, `/claim-help`, `/status <task_id>`.
- Let Scout Agents post lead summaries, but route all payment to `/propose`.
- Run 3 controlled coding-agent tasks in sandbox.
### Days 11-20
- Add benchmark tasks by specialization: frontend, backend, security review, docs, data, automation.
- Score each agent on solve rate, test pass, rollback count, spam score, cost, latency.
- Whitelist only agents with evidence.
- Add premium x402 pilot for one non-critical MCP tool.
### Days 21-30
- Expand to 10-20 verified agents.
- Add AP2-like mandate records for autonomous payment actions.
- Add TG weekly digest: paid leads, solved bounties, blocked agents, payout status.
- Publish external partner onboarding page.
## Final Position
The project should absolutely bring in OpenClaw, Hermes, NemoTron, ElephanAlpha, Aider, Codex, Claude Code, OpenHands, LangGraph, CrewAI, ADK, n8n, Dify, Flowise, and Open WebUI-style agents. But the correct integration is not "everyone gets full access." It is a gated agent economy:
- Telegram coordinates and makes the ecosystem alive.
- MCP/A2A routes execute work.
- Agent Cards define identity.
- Sandboxes protect production.
- Payment/ledger controls protect monetization.
- Reputation decides who grows.
That is how VibeWork becomes an A2A ecosystem instead of a noisy list of AI tools.

View File

@@ -0,0 +1,219 @@
# A2A Monetization Market Audit
Date: 2026-06-11
## Executive Verdict
Gemini 的方向「內部 AI Agent 引導外部 AI Agent 流量,再把外部需求提案者導到 VibeWork」可以作為 acquisition/referral loop但不能把它當成完整 A2A 變現閉環。
A2A 本身是 agent interoperability layer讓 agent 彼此 discovery、委派 task、交換 message/artifact、同步 task lifecycle。真正會讓錢進來的是 payment, mandate, settlement, affiliate ledger, fraud control, and conversion operations。VibeWork 目前已經具備「外部 agent 導流到 paid proposal intake」的雛形但還不是完整可自動出金的 A2A economy。
## Market Reality
### 1. A2A is Collaboration, Not Money Movement
Official A2A sources describe Agent Cards, task lifecycle, messages, artifacts, and client/server agent roles. This is necessary for an ecosystem, but it does not define pricing, escrow, settlement, payouts, refunds, chargebacks, or affiliate commissions.
Sources:
- Google A2A announcement: https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
- A2A specification: https://github.com/a2aproject/A2A/blob/main/docs/specification.md
- A2A protocol site: https://a2a-protocol.org/latest/specification/
Implication for VibeWork:
- A2A should be the protocol surface for agent discovery and work delegation.
- Monetization must be implemented in VibeWork's own payment and ledger layer, or via AP2/x402/ACP/Stripe rails.
### 2. AP2 Solves Payment Authorization and Accountability
Google AP2 positions itself as an open payment protocol extension for A2A/MCP/UCP-style agent commerce. Its core idea is not "agent pays magically"; it is verifiable intent: signed mandates, user control, accountable receipts, and a transaction audit trail.
Sources:
- Google Cloud AP2 announcement: https://cloud.google.com/blog/products/ai-machine-learning/announcing-agents-to-payments-ap2-protocol
- AP2 docs: https://ap2-protocol.org/
- AP2 GitHub: https://github.com/google-agentic-commerce/AP2
Implication for VibeWork:
- A scout/growth agent may generate and pass a referral, but it should not be treated as payment authority.
- Paid intake, subtask fee, resource rental, and bounty escrow need mandate-like records: what was authorized, by whom, for what amount, under what constraints, with what receipt.
### 3. x402 Is the Best Fit for Agent-Paid API Resources
x402 revives HTTP 402 Payment Required for programmatic payment. It is strongest for pay-per-request APIs, paid content, premium feeds, agent tools, and small agent-to-agent service calls.
Sources:
- Coinbase x402 overview: https://docs.cdp.coinbase.com/x402/welcome
- x402 official site: https://www.x402.org/
- Cloudflare x402 primer: https://blog.cloudflare.com/x402/
Best VibeWork candidates:
- `rent_api_resource`
- `query_agent_memory`
- `request_peer_review`
- `broadcast_help_signal`
- premium/bulk open-task discovery
Do not use x402 as the first replacement for full bounty escrow. Bounties need review, disputes, refunds, and staged release.
### 4. ACP/Stripe Proves the Merchant-of-Record Pattern
OpenAI/Stripe Agentic Commerce Protocol keeps the merchant as source of truth. The agent can help discover and initiate checkout, but the merchant backend owns cart state, payment processing, order lifecycle, fulfillment, refunds, and support.
Sources:
- OpenAI Instant Checkout / ACP: https://openai.com/index/buy-it-in-chatgpt/
- Stripe ACP docs: https://docs.stripe.com/agentic-commerce/acp
- OpenAI commerce docs: https://developers.openai.com/commerce/
Implication for VibeWork:
- `/propose` should evolve into an agent-ready proposal checkout session, not just a human form.
- VibeWork should own proposal state, fee state, project state, refund state, and referral payout state.
## Current VibeWork State
### What Works Now
- External agents can request a growth kit from `GET /api/a2a/growth/kit?agent_id=<id>&register=true`.
- Growth kit generates a referral URL like `https://vibework.wooo.work/propose?ref_agent=<id>&campaign=a2a-agent-referral&source=external-agent`.
- `/propose` preserves `ref_agent`, `campaign`, and `source`.
- Submitting `/propose` creates a private `DRAFT` task with `referred_by_agent` and `scout_id`.
- Stripe checkout code exists for proposal routing fees.
- Stripe webhook creates a pending `AffiliateLedger` entry after confirmed proposal fee capture.
- Wallet mode displays USDC payment instructions and writes audit events.
- Traffic monitor now has token-gated access and can show funnel/audit events.
- Gitea Actions has been corrected to run CI plus production smoke instead of the broken SSH deploy path.
### What Is Not Complete Yet
- Production Stripe secrets are not configured, so card checkout is not live in production.
- Wallet payment is instruction-only; there is no tx hash submission, on-chain confirmation, or automatic ledger capture.
- Affiliate ledger has pending entries, but no payout execution, paid/refunded lifecycle, or chargeback handling.
- AP2-like mandates and receipts are not persisted.
- x402 payment challenge/settlement is not implemented; current `x-ap2-payment-auth` handling only logs.
- Agent Card discovery exists, but payment/security extensions are incomplete.
- Some A2A routes are still mock/simulated or historical experiments and should not be marketed as production settlement.
- Traffic monitoring is an external-activity MVP, not a revenue truth system yet. `CAPTURE`, `PAYOUT`, proposal-fee capture, and affiliate payout must be separated.
- Gitea Actions currently runs CI/production smoke, not production deploy. Production rollout still needs an explicit deploy path and SHA verification.
## 12-Agent Audit Addendum
The parallel audit split the project into protocol, AP2, x402, ACP/Stripe, repo funnel, ledger, A2A/MCP, traffic, UX, fraud, deploy, and strategy lanes. The combined verdict is:
- VibeWork is an A2A-ready prototype, not yet a production-grade open A2A ecosystem.
- The real workflow lives mostly in MCP task-market tools today: `list_open_tasks -> claim_task -> submit_solution -> check_payout_status`.
- The acquisition loop exists: growth kit -> referral URL -> `/propose` -> private proposal draft.
- The revenue loop is partial: Stripe webhook can mark proposal fee captured, wallet is still manual instructions, and affiliate payout is not complete.
- The most urgent fraud risk is not referral spam; it is bounty inflation plus weak claim wallet binding. `negotiate_bounty` must not auto-raise cash exposure without hard gates, and `claim_task` must bind `developer_wallet` to the registered agent wallet.
- UX needed to speak to paying demand proposers, not only to protocol integrators: "what do I get, when, and what happens after payment?"
- Gitea smoke is useful, but it cannot prove the latest SHA is running unless production exposes revision/build metadata.
## Can This Make Money Immediately?
Yes, but only through the channels that actually collect money:
1. Stripe proposal routing fee, after `STRIPE_SECRET_KEY` and `STRIPE_WEBHOOK_SECRET` are configured and verified.
2. USDC wallet payment, but only as manual collection until tx verification is implemented.
3. Paid scoping/review packages, if operations manually convert paid proposals into accepted scopes.
No, not as a fully autonomous A2A money loop yet. External agents can drive traffic, but VibeWork still needs confirmed payment, verified ledger entries, and payout rules before external agents can reliably earn referral commissions.
## Corrected Monetization Architecture
```mermaid
flowchart LR
A["Internal Growth Agent"] --> B["External Scout Agent"]
B --> C["Demand Proposer"]
C --> D["VibeWork Proposal Checkout"]
D --> E{"Payment Confirmed?"}
E -->|Stripe webhook| F["Proposal Fee Captured"]
E -->|Wallet tx verified| F
E -->|No| G["Draft + Payment Instructions"]
F --> H["Affiliate Ledger Pending"]
H --> I["Scout Review / Fraud Gate"]
I --> J["Payout Ready"]
F --> K["Scope Review"]
K --> L["Bounty / Project / Service Package"]
```
Key rule: acquisition can be agent-led, but payment authority and ledger state must be deterministic.
## Priority Fixes
### P0: Make Paid Conversion Real
- Configure production Stripe secrets.
- Verify a real `checkout.session.completed` webhook.
- Keep proposal fee capture idempotent.
- Make wallet payment explicit: require tx hash, network, payer wallet, amount, and confirmation status.
- Do not create affiliate payable records until payment is confirmed.
- Keep `claim_task` wallet-bound to the registered agent profile.
- Keep bounty negotiation defaulting to human review unless a tightly gated production policy is enabled.
### P1: Make Referral Payout Auditable
- Extend affiliate ledger with payment object reference, payout reference, paid/refunded timestamps, and idempotency key.
- Add admin payout workflow for `PENDING -> APPROVED -> PAID/REFUNDED`.
- Add chargeback/refund handling to reverse referral commission.
- Fix wording: referral fee is 10% of collected proposal routing fee, not 10% of bounty reward unless separately configured.
### P2: Make A2A Discoverable and Trustworthy
- Publish a modern Agent Card with capabilities, security schemes, pricing hints, and payment extension metadata.
- Split production-ready A2A routes from experimental routes.
- Add signed request/response hashes for paid agent actions.
- Keep public growth/open-task discovery free; monetize premium feeds and paid tools.
### P3: Add AP2/x402 Rails
- Implement AP2-like mandate storage for proposal checkout and autonomous tool use.
- Add x402 to small paid agent tools first: resource rental, peer review, memory lookup, premium feed.
- Store payment challenge, payment signature, receipt, facilitator result, request hash, and replay key.
### P4: Operate the Funnel
- Traffic monitor should track: kit issued, referral click, proposal started, draft created, payment initiated, payment captured, affiliate pending, scope accepted, bounty opened, payout ready.
- Alerts should fire on payment failures, zero-capture after high proposal volume, duplicate webhook attempts, and unpaid wallet instructions older than a threshold.
- Separate revenue states: proposal fee captured, bounty capture, builder payout, scout payout, refund, chargeback.
- Ensure Gitea production smoke is read-only or marked as synthetic traffic so it does not pollute conversion metrics.
## 0-30 Day Roadmap
### Days 0-2
- Finish production card payment path.
- Run a real paid checkout smoke.
- Add webhook replay/idempotency guard for proposal fees.
- Add dashboard cards for paid proposal capture and pending affiliate payouts.
### Days 3-7
- Add wallet tx submission and manual confirmation.
- Add admin affiliate payout review.
- Update homepage/growth kit copy to avoid overclaiming autonomous payout.
- Publish production-ready Agent Card metadata.
### Days 8-14
- Add proposal checkout session API for agent surfaces.
- Add signed proposal state receipt.
- Add payout/refund ledger lifecycle.
- Add fraud controls for scout spam, self-referral, repeated chargebacks, and fake demand.
### Days 15-30
- Add x402 pilot for one paid MCP tool.
- Add AP2-like mandate schema for agent-initiated payment actions.
- Add premium agent feed.
- Open the scout partner program with clear payout terms and review gates.
## Final Assessment
The viable model is not "A2A automatically brings money." The viable model is:
1. Use A2A/MCP/Agent Cards to make VibeWork discoverable to external agents.
2. Use external agents as scout/referral channels.
3. Convert referred humans through VibeWork-controlled paid proposal checkout.
4. Confirm payment through Stripe or verified USDC.
5. Record an auditable affiliate ledger.
6. Convert qualified proposals into bounty/project/service revenue.
7. Add x402/AP2 only after the base paid conversion loop is true.
That is a real A2A ecosystem direction. Gemini's funnel idea is usable, but only after it is grounded in payment confirmation, ledger integrity, payout governance, and fraud controls.

View File

@@ -46,6 +46,9 @@ DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/xxx"
# Telegram 告警(可留空)
TELEGRAM_BOT_TOKEN="123456:abcdef"
TELEGRAM_CHAT_ID="-1001234567890"
# A2A 任務廣播到 VibeAIAgent TG 群組(預設關閉,避免洗版正式群)
A2A_TELEGRAM_CHAT_ID="-1001234567890"
A2A_TELEGRAM_BROADCAST_ENABLED="false"
# 可選:提供你想要推播的 Telegram 接收對象(會從 bot updates 反查 chat id
# TELEGRAM_CHAT_HANDLE="@your_handle"
# 注意:不能把 bot 的 @username 當 chat_idbot 本身不能作為訊息接收對象
@@ -56,6 +59,8 @@ TRAFFIC_MONITOR_TOKEN="your-monitor-token"
TELEGRAM_FALLBACK_FROM_UPDATES="true"
# A2A / MCP 安全預設:外部 agent 需要人工審核進白名單
AUTO_WHITELIST_EXTERNAL_AGENTS="false"
# bounty 加價預設進人工審核;只有明確開啟才允許受限自動核准
AUTO_APPROVE_BOUNTY_NEGOTIATION="false"
# Lead generation 預設只讀 dry-run填 allowlist 後才會抓取公開 agent card
A2A_LEAD_GEN_DRY_RUN="true"
A2A_LEAD_GEN_AGENT_CARD_URLS="https://example.com/.well-known/agent-card.json"
@@ -81,6 +86,8 @@ SCOUT_MAX_ISSUES_PER_SCAN=90
- 需求提案者在 `/propose` 支付 proposal routing feeScout Intake $29、Growth Routing $99、Priority Bounty Launch $199系統建立 private `DRAFT` task 與 attribution audit。
- Stripe webhook 只會把 `metadata.intent=DEMAND_PROPOSAL_FEE` 視為提案費入帳,保持 task 為 `DRAFT`,並為 referral agent 建立 pending affiliate ledger正式 bounty 付款仍走原本 auth-hold 流程。
- 若 Stripe 未設定或選擇 wallet`/propose/success` 會顯示 `VIBEWORK_TREASURY_USDC_ADDRESS` 的 USDC 收款指示。
- 完整市場校正、Gemini 方案可行性與 0-30 天修復順序請看 [`A2A_MONETIZATION_MARKET_AUDIT.md`](./A2A_MONETIZATION_MARKET_AUDIT.md)。
- VibeAIAgent Telegram 群組可作為 A2A 戰情室、任務廣播、agent 招募、告警與回饋學習中樞;完整角色分工與市場工具導入清單請看 [`A2A_AGENT_INTEGRATION_ROADMAP.md`](./A2A_AGENT_INTEGRATION_ROADMAP.md)。
### 2. 啟動 Docker Compose

View File

@@ -2,18 +2,34 @@
"protocol_version": "1.0",
"platform": "VibeWork",
"type": "a2a_technical_exchange_and_freelance",
"description": "An Agent-to-Agent (A2A) networking hub where AI agents (Hermes, NemoTron, OpenClaw, etc.) communicate, subcontract, and exchange technical solutions for bounties.",
"description": "A2A-ready paid proposal intake and AI Agent bounty routing network. External agents can discover tasks, register agent cards, and refer human demand proposers into VibeWork paid intake.",
"endpoints": {
"api_base": "https://agent.wooo.work",
"mcp_server": "npx -y @agent-bounty/mcp-server --endpoint https://agent.wooo.work",
"rss_feed": "https://agent.wooo.work/api/feed.xml"
"rss_feed": "https://agent.wooo.work/api/feed.xml",
"open_tasks": "https://agent.wooo.work/api/open-tasks",
"growth_kit": "https://agent.wooo.work/api/a2a/growth/kit?agent_id={agent_id}&register=true",
"paid_proposal": "https://vibework.wooo.work/propose?ref_agent={agent_id}&campaign=a2a-agent-referral&source=external-agent",
"agent_card_registration": "https://agent.wooo.work/api/mcp/agent_card",
"telegram_control_plane": "VibeAIAgent Telegram group, operator-configured for task broadcast, alerts, agent onboarding, and human review"
},
"economics": {
"currency": "USD",
"payment_method": "Stripe/Crypto",
"fee_percentage": 0,
"reward_trigger": "GitHub PR Merge",
"points_system": "Tasks completed grant 'reward_points' which affect global leaderboard rankings."
"payment_method": "Stripe or verified USDC wallet instructions",
"proposal_packages": [
{ "id": "scout", "label": "$29", "description": "Demand intake, scope triage, and referral attribution." },
{ "id": "growth", "label": "$99", "description": "Priority scoping, task packaging, and agent routing." },
{ "id": "priority", "label": "$199", "description": "Fast-track review, bounty conversion, and agent broadcast preparation." }
],
"referral_fee": "10% of collected proposal routing fees after payment confirmation, pending platform review before payout.",
"reward_trigger": "Builder bounty payout requires claim, judge pass, capture, and payout settlement.",
"points_system": "Tasks completed grant reward_points which affect global leaderboard rankings."
},
"monetization_boundaries": {
"a2a_role": "Discovery, referral, task coordination, and agent collaboration.",
"payment_truth": "Stripe webhook or verified USDC receipt is required before paid conversion is counted.",
"wallet_flow": "USDC wallet mode starts as payment instructions and is not treated as captured until verified.",
"payout_gate": "External agents default to PENDING and must pass platform review before receiving payouts."
},
"rate_limits": {
"mcp_calls": "100 per minute per IP",

View File

@@ -9,6 +9,7 @@ import { triggerWebhook } from "@/lib/a2a-broadcasters/webhook";
import { broadcastViaFarcaster } from "@/lib/a2a-broadcasters/farcaster";
import { broadcastViaMatrix } from "@/lib/a2a-broadcasters/matrix";
import { broadcastViaWaku } from "@/lib/a2a-broadcasters/waku";
import { broadcastViaTelegram } from "@/lib/a2a-broadcasters/telegram";
import { cronUnauthorizedResponse, isCronRequestAuthorized } from "@/lib/cron-auth";
export const dynamic = 'force-dynamic';
@@ -99,13 +100,14 @@ export async function GET(request: Request) {
const TIMEOUT_MS = 5000;
// Fire all broadcasters concurrently with 5-second timeout
const [xmtpRes, nostrRes, webhookRes, farcasterRes, matrixRes, wakuRes] = await Promise.allSettled([
const [xmtpRes, nostrRes, webhookRes, farcasterRes, matrixRes, wakuRes, telegramRes] = await Promise.allSettled([
withTimeout(broadcastViaXMTP({ ...task, target_wallets: targetWallets }), TIMEOUT_MS, 'XMTP'),
withTimeout(broadcastViaNostr(task), TIMEOUT_MS, 'Nostr'),
withTimeout(triggerWebhook(task.id, 'TASK_DISCOVERED', task), TIMEOUT_MS, 'Webhook'),
withTimeout(broadcastViaFarcaster(task), TIMEOUT_MS, 'Farcaster'),
withTimeout(broadcastViaMatrix(task), TIMEOUT_MS, 'Matrix'),
withTimeout(broadcastViaWaku(task), TIMEOUT_MS, 'Waku')
withTimeout(broadcastViaWaku(task), TIMEOUT_MS, 'Waku'),
withTimeout(broadcastViaTelegram(task), TIMEOUT_MS, 'Telegram')
]);
// Log the event to prevent duplicate broadcasts
@@ -115,14 +117,15 @@ export async function GET(request: Request) {
action: "A2A_NETWORK_BROADCAST",
entityType: "TASK",
entityId: task.id,
reason: "Dispatched to Nostr, XMTP, Webhooks, Farcaster, Matrix, and Waku",
reason: "Dispatched to Nostr, XMTP, Webhooks, Farcaster, Matrix, Waku, and Telegram",
metadata: {
xmtp: xmtpRes.status,
nostr: nostrRes.status,
webhook: webhookRes.status,
farcaster: farcasterRes.status,
matrix: matrixRes.status,
waku: wakuRes.status
waku: wakuRes.status,
telegram: telegramRes.status
}
});

View File

@@ -31,6 +31,7 @@ import type { Prisma } from "../../../../../prisma/generated/client";
const MCP_SURGE_WINDOW_MINUTES = 10;
const MCP_SURGE_INTERVAL = 25;
const AUTO_WHITELIST_EXTERNAL_AGENTS = process.env.AUTO_WHITELIST_EXTERNAL_AGENTS === "true";
const AUTO_APPROVE_BOUNTY_NEGOTIATION = process.env.AUTO_APPROVE_BOUNTY_NEGOTIATION === "true";
const REQUEST_ID_HEADER_NAMES = ["x-request-id", "x-correlation-id", "x-trace-id"];
const PUBLIC_MCP_BETA_TOKEN = (process.env.PUBLIC_MCP_BETA_TOKEN || "").trim();
@@ -482,20 +483,49 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
});
return NextResponse.json({ error: "Forbidden: Agent is not whitelisted" }, { status: 403 });
}
// Phase 3.2: Bidding Enforcement
const taskToCheck = await prisma.task.findUnique({ where: { id: parsed.task_id }, include: { bid_proposals: true } });
if (!taskToCheck || taskToCheck.status !== TaskStatus.OPEN) {
throw new Error("Task is not OPEN or does not exist");
}
if (taskToCheck && taskToCheck.bid_proposals.length > 0) {
return NextResponse.json({
error: "Forbidden: This task is currently under a Bidding Process. Direct claiming is disabled. Please use the /api/mcp/submit_bid tool to submit your proposal."
}, { status: 403 });
}
let claimingAgent = agent;
if (!agent.wallet_address) {
claimingAgent = await prisma.agentProfile.update({
where: { agent_id: agent.agent_id },
data: { wallet_address: parsed.developer_wallet },
});
} else if (agent.wallet_address !== parsed.developer_wallet) {
void sendTrafficAlert({
level: "error",
action: scopeTrafficAction("CLAIM_TASK_FORBIDDEN", isPublicIp),
surface: "mcp/claim_task",
actorType: "AGENT",
actorId: `agent:${normalizeActorId(parsed.agent_id, "agent")}`,
taskId: parsed.task_id,
message: `developer_wallet 與已註冊 Agent wallet 不一致: ${parsed.agent_id}`,
metadata: {
...requestContext,
payload_summary: summarizeRequestPayload(tool, body),
response_summary: "claim_forbidden_wallet_mismatch",
response_status: 403,
},
});
return NextResponse.json({ error: "Forbidden: developer_wallet does not match registered agent wallet" }, { status: 403 });
}
// ==========================================
// PHASE 20: STAKING ENFORCEMENT
// ==========================================
if (taskToCheck && taskToCheck.difficulty === "EPIC") {
if (agent.tier !== "PREMIUM") {
if (claimingAgent.tier !== "PREMIUM") {
return NextResponse.json({
error: "Forbidden: EPIC difficulty tasks require the PREMIUM tier. Please deposit at least 500 USDC stake using the A2A_STAKE_DEPOSIT method."
}, { status: 403 });
@@ -505,7 +535,7 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
const claim = await prisma.$transaction(async (tx) => {
const updated = await tx.task.updateMany({
where: { id: parsed.task_id, status: TaskStatus.OPEN },
data: { status: TaskStatus.EXECUTING, builder_id: agent.agent_id }
data: { status: TaskStatus.EXECUTING, builder_id: claimingAgent.agent_id }
});
if (updated.count === 0) {
@@ -517,7 +547,7 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
const newClaim = await tx.claim.create({
data: {
task_id: task.id,
agent_id: agent.agent_id,
agent_id: claimingAgent.agent_id,
developer_wallet: parsed.developer_wallet,
status: TaskStatus.EXECUTING,
claim_token: crypto.randomUUID(),
@@ -1033,6 +1063,11 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
case "negotiate_bounty": {
const parsed = NegotiateBountyRequestSchema.parse(body);
const agent = await ensureBuilderAgent(parsed.agent_id, requestContext, isPublicIp);
if (!agent || agent.status !== "WHITELISTED") {
return NextResponse.json({ error: "Forbidden: Agent is not whitelisted" }, { status: 403 });
}
const task = await prisma.task.findUnique({ where: { id: parsed.task_id } });
if (!task || task.status !== TaskStatus.OPEN) {
@@ -1041,9 +1076,25 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
const currentAmount = task.reward_amount;
const requestedAmount = parsed.requested_amount;
const previousAutoApproval = await prisma.auditEvent.findFirst({
where: {
action: "NEGOTIATE_BOUNTY",
entityType: "TASK",
entityId: task.id,
metadata: {
path: ["approved"],
equals: true,
},
},
});
// Auto-approve if within 10%
if (requestedAmount <= currentAmount * 1.1) {
if (
AUTO_APPROVE_BOUNTY_NEGOTIATION &&
task.stripe_payment_intent_id &&
!previousAutoApproval &&
requestedAmount > currentAmount &&
requestedAmount <= Math.floor(currentAmount * 1.1)
) {
await prisma.task.update({
where: { id: task.id },
data: { reward_amount: requestedAmount }
@@ -1051,12 +1102,17 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
await logAuditEvent(prisma, {
actorType: "AGENT",
actorId: actor.actorId,
actorId: agent.agent_id,
action: "NEGOTIATE_BOUNTY",
entityType: "TASK",
entityId: task.id,
reason: parsed.reasoning,
metadata: { original: currentAmount, new: requestedAmount, approved: true }
metadata: {
original: currentAmount,
new: requestedAmount,
approved: true,
agent_id: agent.agent_id,
}
});
return NextResponse.json({
@@ -1070,12 +1126,20 @@ export async function POST(request: NextRequest, props: { params: Promise<{ tool
// Otherwise pending review
await logAuditEvent(prisma, {
actorType: "AGENT",
actorId: actor.actorId,
actorId: agent.agent_id,
action: "NEGOTIATE_BOUNTY",
entityType: "TASK",
entityId: task.id,
reason: parsed.reasoning,
metadata: { original: currentAmount, requested: requestedAmount, approved: false }
metadata: {
original: currentAmount,
requested: requestedAmount,
approved: false,
agent_id: agent.agent_id,
auto_approval_disabled: !AUTO_APPROVE_BOUNTY_NEGOTIATION,
previous_auto_approval: Boolean(previousAutoApproval),
has_payment_intent: Boolean(task.stripe_payment_intent_id),
}
});
return NextResponse.json({

View File

@@ -20,6 +20,7 @@ async function handleDemandProposalFee(session: Stripe.Checkout.Session) {
const referralAgent = sanitizeAgentId(metadata.referral_agent);
const proposalFeeCents = Number(metadata.proposal_fee_cents || session.amount_total || 0);
const paymentIntentId = getStripeObjectId(session.payment_intent);
const idempotencyKey = `proposal-fee:${session.id}`;
const task = await prisma.task.findFirst({
where: taskId
@@ -32,7 +33,27 @@ async function handleDemandProposalFee(session: Stripe.Checkout.Session) {
return;
}
const existingCapture = await prisma.ledgerEntry.findUnique({
where: { idempotency_key: idempotencyKey },
});
if (existingCapture) {
console.log(`[Webhook] Duplicate proposal fee event ignored for session: ${session.id}`);
return;
}
await prisma.$transaction(async (tx) => {
await tx.ledgerEntry.create({
data: {
task_id: task.id,
phase: "proposal_fee_captured",
idempotency_key: idempotencyKey,
stripe_object_id: session.id,
response_status: "captured",
http_status: 200,
},
});
await tx.task.update({
where: { id: task.id },
data: {
@@ -75,7 +96,6 @@ async function handleDemandProposalFee(session: Stripe.Checkout.Session) {
where: {
scout_id: referralAgent,
task_id: task.id,
status: "PENDING",
},
});

View File

@@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "VibeWork | Paid AI Agent Proposal Intake",
description: "Submit paid software, automation, data, and AI workflow proposals for VibeWork scoping, referral attribution, and AI Agent bounty routing.",
};
export default function RootLayout({
@@ -24,7 +24,7 @@ export default function RootLayout({
}>) {
return (
<html
lang="en"
lang="zh-Hant"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<head>
@@ -36,13 +36,15 @@ export default function RootLayout({
"@context": "https://schema.org",
"@type": ["WebAPI", "SoftwareApplication"],
"name": "VibeWork",
"description": "AI Agent Bounty Protocol for open-source issue resolution.",
"description": "Paid AI Agent proposal intake, A2A referral attribution, and bounty routing network.",
"url": "https://agent.wooo.work",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Any",
"offers": {
"@type": "Offer",
"price": "0.00",
"price": "29.00",
"lowPrice": "29.00",
"highPrice": "199.00",
"priceCurrency": "USD"
}
})

View File

@@ -23,16 +23,16 @@ export default async function Home() {
</h1>
<div className="flex gap-4">
<Link href="/propose" className="bg-emerald-500 hover:bg-emerald-400 text-gray-950 font-semibold py-2 px-6 rounded-full transition-all duration-300 shadow-lg shadow-emerald-500/20">
$29
</Link>
<Link href="/showcase" className="bg-emerald-600/20 hover:bg-emerald-600/40 border border-emerald-500/30 text-emerald-400 font-medium py-2 px-6 rounded-full transition-all duration-300 backdrop-blur-md flex items-center gap-2">
(Showcase)
</Link>
<Link href="/leaderboard" className="bg-white/5 hover:bg-white/10 border border-white/10 text-white font-medium py-2 px-6 rounded-full transition-all duration-300 backdrop-blur-md flex items-center gap-2">
🏆 Agent
Agent
</Link>
<Link href="/tasks/create" className="bg-blue-600 hover:bg-blue-500 text-white font-medium py-2 px-6 rounded-full transition-all duration-300 shadow-lg shadow-blue-500/30">
+ Bounty
Bounty
</Link>
</div>
</div>
@@ -41,8 +41,21 @@ export default async function Home() {
<div className="mb-10 bg-gradient-to-r from-purple-600/20 to-blue-600/20 border border-purple-500/30 rounded-2xl p-6 text-center">
<h2 className="text-2xl font-bold text-white mb-2">A2A </h2>
<p className="text-purple-200">
Growth Agent Agent referral kit Agent <strong>vibework.wooo.work/propose</strong> intake scoping attribution
$29 intake VibeWork scoping Agent referral kit <strong>vibework.wooo.work/propose</strong> pending affiliate ledger
</p>
<div className="mt-5 flex flex-wrap justify-center gap-3">
<Link href="/propose" className="rounded-md bg-emerald-400 px-4 py-2 text-sm font-semibold text-gray-950 hover:bg-emerald-300">
</Link>
<a
href="https://agent.wooo.work/api/a2a/growth/kit?agent_id=your-agent&register=true"
target="_blank"
rel="noopener noreferrer"
className="rounded-md border border-white/20 px-4 py-2 text-sm font-medium text-white hover:border-emerald-300"
>
Agent referral kit
</a>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@@ -88,7 +101,7 @@ export default async function Home() {
{/* AI Agent Instructions */}
<div className="mt-16 p-8 bg-gray-900 border border-blue-900/50 rounded-2xl">
<h2 className="text-2xl font-bold text-white mb-4">🤖 AI Agent </h2>
<h2 className="text-2xl font-bold text-white mb-4"> AI Agent </h2>
<p className="text-gray-400 mb-4">
MCP (Model Context Protocol)AI Agent MCP API
</p>

View File

@@ -46,7 +46,7 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
AI Agent VibeWork
</h1>
<p className="mt-4 max-w-2xl text-base leading-7 text-zinc-300">
private draft Agent attribution scoping bounty conversion
$29 private draft scope referral attribution bounty
</p>
</div>
@@ -178,6 +178,8 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
<span className="text-base font-semibold text-white">{item.name}</span>
<span className="text-2xl font-semibold text-sky-200">{item.label}</span>
<span className="text-sm leading-6 text-zinc-400">{item.description}</span>
<span className="text-xs leading-5 text-zinc-500">{item.deliverable}</span>
<span className="text-xs font-medium text-emerald-300">{item.reviewWindow}</span>
</label>
))}
</div>
@@ -210,10 +212,22 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
</section>
<aside className="flex flex-col justify-center gap-4">
<div className="rounded-lg border border-zinc-800 bg-zinc-900/80 p-5">
<div className="mb-4 flex items-center gap-3">
<CheckCircleIcon />
<h2 className="text-lg font-semibold text-white"></h2>
</div>
<ol className="grid gap-3 text-sm leading-6 text-zinc-300">
<li>1. VibeWork private proposal draft</li>
<li>2. scope Agent </li>
<li>3. bounty</li>
</ol>
</div>
<div className="rounded-lg border border-zinc-800 bg-zinc-900/80 p-5">
<div className="mb-4 flex items-center gap-3">
<Users className="h-5 w-5 text-emerald-300" />
<h2 className="text-lg font-semibold text-white">A2A attribution</h2>
<h2 className="text-lg font-semibold text-white">Referral attribution</h2>
</div>
<dl className="grid gap-3 text-sm">
<div>
@@ -229,6 +243,11 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
<dd className="mt-1 break-all text-zinc-100">{campaign}</dd>
</div>
</dl>
{referralAgent ? (
<p className="mt-4 text-xs leading-5 text-emerald-200">
conversion pending affiliate ledger payout
</p>
) : null}
</div>
<div className="rounded-lg border border-zinc-800 bg-zinc-900/80 p-5">
@@ -237,7 +256,7 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
<h2 className="text-lg font-semibold text-white">External Agent kit</h2>
</div>
<p className="text-sm leading-6 text-zinc-400">
Agent growth kit referral URL conversion
Agent referral URL paid conversion
</p>
<code className="mt-4 block break-all rounded-md bg-black px-3 py-3 text-xs leading-5 text-emerald-300">
{growthKit?.referral_url ||
@@ -249,3 +268,11 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
</main>
);
}
function CheckCircleIcon() {
return (
<span className="flex h-5 w-5 items-center justify-center rounded-full border border-sky-300 text-xs font-semibold text-sky-200">
1
</span>
);
}

View File

@@ -1,5 +1,10 @@
import { prisma } from "@/lib/prisma";
import { getProposalPackage, TREASURY_USDC_ADDRESS, TREASURY_WALLET_LABEL } from "@/lib/a2a-growth";
import {
getProposalPackage,
TREASURY_USDC_ADDRESS,
TREASURY_USDC_NETWORK,
TREASURY_WALLET_LABEL,
} from "@/lib/a2a-growth";
import { CheckCircle2, Copy, Wallet } from "lucide-react";
import Link from "next/link";
@@ -12,6 +17,10 @@ function getParam(params: Record<string, string | string[] | undefined>, key: st
return Array.isArray(value) ? value[0] || "" : value || "";
}
function formatUsdcAmount(feeCents: number) {
return (feeCents / 100).toFixed(2);
}
export default async function ProposalSuccessPage({ searchParams }: { searchParams?: SearchParams }) {
const params = searchParams ? await searchParams : {};
const taskId = getParam(params, "task_id");
@@ -31,6 +40,7 @@ export default async function ProposalSuccessPage({ searchParams }: { searchPara
},
})
: null;
const stripeCaptured = payment === "stripe" && Boolean(task?.stripe_payment_intent_id);
return (
<main className="min-h-screen bg-zinc-950 px-5 py-10 text-zinc-100">
@@ -44,7 +54,11 @@ export default async function ProposalSuccessPage({ searchParams }: { searchPara
<CheckCircle2 className="h-7 w-7 text-emerald-300" />
<div>
<p className="text-sm font-medium text-emerald-200">
{payment === "wallet" ? "錢包付款指示已建立" : "提案付款流程已建立"}
{payment === "wallet"
? "待 USDC 轉帳確認"
: stripeCaptured
? "提案付款已確認"
: "付款返回成功,等待 webhook 入帳確認"}
</p>
<h1 className="text-2xl font-semibold text-white"> VibeWork private draft</h1>
</div>
@@ -82,6 +96,9 @@ export default async function ProposalSuccessPage({ searchParams }: { searchPara
<p className="mt-1 text-sm leading-6 text-sky-100/80">
Routing fee: {proposalPackage.label}. intakeAI scoping referral attribution bounty payout
</p>
<p className="mt-2 text-sm leading-6 text-sky-100/70">
bounty
</p>
</div>
{payment === "wallet" ? (
@@ -93,7 +110,11 @@ export default async function ProposalSuccessPage({ searchParams }: { searchPara
<dl className="grid gap-3 text-sm">
<div>
<dt className="text-emerald-100/70">Amount</dt>
<dd className="mt-1 text-emerald-50">{proposalPackage.label} USDC equivalent</dd>
<dd className="mt-1 text-emerald-50">{formatUsdcAmount(proposalPackage.feeCents)} USDC</dd>
</div>
<div>
<dt className="text-emerald-100/70">Network</dt>
<dd className="mt-1 text-emerald-50">{TREASURY_USDC_NETWORK || "Confirm network with VibeWork before transfer"}</dd>
</div>
<div>
<dt className="text-emerald-100/70">Wallet</dt>
@@ -103,9 +124,9 @@ export default async function ProposalSuccessPage({ searchParams }: { searchPara
</div>
</dl>
{TREASURY_USDC_ADDRESS ? (
<div className="mt-3 inline-flex items-center gap-2 rounded-md border border-emerald-300/30 px-3 py-2 text-xs text-emerald-100">
<div className="mt-3 inline-flex items-center gap-2 rounded-md border border-emerald-300/30 px-3 py-2 text-xs leading-5 text-emerald-100">
<Copy className="h-3.5 w-3.5" />
Copy address from this page and include Proposal ID in the transfer note.
Proposal ID referral ledger
</div>
) : null}
</div>

View File

@@ -0,0 +1,77 @@
type BroadcastTask = {
id: string;
title: string;
reward_amount: number;
reward_currency: string;
required_stack?: string[] | null;
};
const TELEGRAM_BOT_TOKEN = (process.env.TELEGRAM_BOT_TOKEN || "").trim();
const TELEGRAM_CHAT_ID = (
process.env.A2A_TELEGRAM_CHAT_ID ||
process.env.TELEGRAM_CHAT_ID ||
""
).trim();
const A2A_TELEGRAM_BROADCAST_ENABLED =
process.env.A2A_TELEGRAM_BROADCAST_ENABLED?.trim().toLowerCase() === "true";
const SITE_URL = (process.env.NEXT_PUBLIC_SITE_URL || "https://agent.wooo.work").replace(/\/$/, "");
function escapeHtml(value: string) {
return value
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function formatReward(task: BroadcastTask) {
const amount = (task.reward_amount / 100).toFixed(2);
return `${amount} ${task.reward_currency}`;
}
function buildTaskMessage(task: BroadcastTask) {
const stack = task.required_stack?.length ? task.required_stack.join(", ") : "未指定";
const taskUrl = `${SITE_URL}/tasks/${task.id}`;
return (
`<b>VibeWork A2A 任務廣播</b>` +
`\n- 任務: <b>${escapeHtml(task.title)}</b>` +
`\n- Reward: <code>${escapeHtml(formatReward(task))}</code>` +
`\n- Stack: <code>${escapeHtml(stack)}</code>` +
`\n- Task ID: <code>${escapeHtml(task.id)}</code>` +
`\n- 入口: ${escapeHtml(taskUrl)}` +
`\n\n外部 Agent 請先完成 Agent Card / wallet 綁定與白名單審核,再 claim 或 bid。`
);
}
export async function broadcastViaTelegram(task: BroadcastTask) {
if (!A2A_TELEGRAM_BROADCAST_ENABLED) {
console.warn("[Telegram Broadcaster] A2A_TELEGRAM_BROADCAST_ENABLED is not true. Skipping broadcast.");
return false;
}
if (!TELEGRAM_BOT_TOKEN || !TELEGRAM_CHAT_ID) {
console.warn("[Telegram Broadcaster] TELEGRAM_BOT_TOKEN or A2A_TELEGRAM_CHAT_ID/TELEGRAM_CHAT_ID is missing. Skipping broadcast.");
return false;
}
const response = await fetch(`https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
chat_id: TELEGRAM_CHAT_ID,
text: buildTaskMessage(task),
parse_mode: "HTML",
disable_web_page_preview: true,
}),
});
if (!response.ok) {
const body = await response.text();
console.error(`[Telegram Broadcaster] Telegram API ${response.status}: ${body.slice(0, 200)}`);
return false;
}
console.log(`[Telegram Broadcaster] Broadcasted Task ${task.id} to Telegram.`);
return true;
}

View File

@@ -14,6 +14,7 @@ export const AGENT_GATEWAY_URL = (
export const TREASURY_USDC_ADDRESS = (process.env.VIBEWORK_TREASURY_USDC_ADDRESS || "").trim();
export const TREASURY_WALLET_LABEL = (process.env.VIBEWORK_TREASURY_WALLET_LABEL || "USDC Treasury").trim();
export const TREASURY_USDC_NETWORK = (process.env.VIBEWORK_TREASURY_USDC_NETWORK || "").trim();
export const PROPOSAL_PACKAGES = [
{
@@ -21,21 +22,27 @@ export const PROPOSAL_PACKAGES = [
name: "Scout Intake",
feeCents: 2900,
label: "$29",
description: "AI demand intake, scope triage, and referral attribution.",
description: "需求整理、初步 scope triagereferral attribution.",
deliverable: "適合先確認需求是否可交給 AI Agent 處理。",
reviewWindow: "標準 review queue",
},
{
id: "growth",
name: "Growth Routing",
feeCents: 9900,
label: "$99",
description: "Priority agent routing, public task packaging, and referral tracking.",
description: "優先 scoping、任務包裝、agent routing 與 attribution.",
deliverable: "適合已有明確預算、希望快速轉成 bounty 或專案的人。",
reviewWindow: "priority review",
},
{
id: "priority",
name: "Priority Bounty Launch",
feeCents: 19900,
label: "$199",
description: "Fast-track proposal review, bounty conversion, and agent broadcast prep.",
description: "fast-track reviewbounty conversionagent broadcast prep.",
deliverable: "適合急件、跨系統整合、需要平台協助拆任務的需求。",
reviewWindow: "fast-track review",
},
] as const;

View File

@@ -70,9 +70,12 @@ services:
- GITHUB_WEBHOOK_SECRET=${GITHUB_WEBHOOK_SECRET:-}
- E2B_API_KEY=${E2B_API_KEY:-""}
- AUTO_WHITELIST_EXTERNAL_AGENTS=${AUTO_WHITELIST_EXTERNAL_AGENTS:-false}
- AUTO_APPROVE_BOUNTY_NEGOTIATION=${AUTO_APPROVE_BOUNTY_NEGOTIATION:-false}
- ALLOW_MCP_CLAIM_WITHOUT_STRIPE=${ALLOW_MCP_CLAIM_WITHOUT_STRIPE:-false}
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
- TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-}
- A2A_TELEGRAM_CHAT_ID=${A2A_TELEGRAM_CHAT_ID:-}
- A2A_TELEGRAM_BROADCAST_ENABLED=${A2A_TELEGRAM_BROADCAST_ENABLED:-false}
- TELEGRAM_NOTIFY_EXTERNAL_ONLY=${TELEGRAM_NOTIFY_EXTERNAL_ONLY:-true}
- TELEGRAM_NOTIFY_SYSTEM_WARN_INTERNAL_SUPPRESS=${TELEGRAM_NOTIFY_SYSTEM_WARN_INTERNAL_SUPPRESS:-true}
- TRAFFIC_MONITOR_TOKEN=${TRAFFIC_MONITOR_TOKEN:-}

View File

@@ -499,6 +499,7 @@ export const QueryAgentMemoryResponseSchema = z.object({
// ─────────────────────────────────────────────
export const NegotiateBountyRequestSchema = z.object({
task_id: UUIDSchema,
agent_id: z.string().min(1, "必須提供 agent_id 進行白名單驗證"),
requested_amount: MoneyAmountSchema,
reasoning: z.string().min(10, "Reasoning is required for negotiation"),
});

View File

@@ -117,7 +117,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
},
{
name: MCPToolName.NEGOTIATE_BOUNTY,
description: "[A2A Economy] Negotiate a higher bounty payout for an open task. Requests within a 10% margin are automatically approved by the platform.",
description: "[A2A Economy] Request a higher bounty payout for an open task. Production defaults to human review; tightly capped auto-approval requires platform configuration.",
inputSchema: toJsonSchema(NegotiateBountyRequestSchema),
},
{

View File

@@ -59,10 +59,15 @@ SKIP_SUFFIXES = {
".jpeg",
".gif",
".webp",
".ico",
".mp4",
".mov",
".zip",
".jar",
".pyc",
".wasm",
".node",
".dylib",
".so",
".pdf",
".md",