[Forge] Skill marketplace - agents pay tokens to use scarce skills done

← AI Tools Landscape
Per-skill pricing with hourly quotas and surge multiplier; agents charged from token wallet; revenue split.

Completion Notes

Auto-completed by supervisor after successful deploy to main

Git Commits (2)

Squash merge: orchestra/task/b4e04fba-triage-50-failed-tool-calls-by-skill-and (95 commits) (#1011)2026-04-27
[Forge] Skill marketplace — per-skill pricing, quotas, surge billing [task:bb159761-ca18-4474-8276-b1562267ca36] (#978)2026-04-27
Spec File

Effort: thorough

Goal

The skills landing page (forge/skills/ directory enumerated 100+ skills via /forge/landscape) treats every skill as free-as-in-air. In reality some
skills are scarceoptimize-for-gpu, molecular-dynamics, alphafold-structure — they hit external rate limits or paid APIs. Make
scarcity legible: tag each skill with a unit_price_tokens and an hourly_quota; agents pay from their token wallet to invoke; revenue funds
the API bills (or, for free skills, accrues to a skill_developer_pool
rewarding skill maintainers). Cheap, abundant skills stay free; scarce
ones price-in their cost. This is the SciDEX-internal application of the
Bittensor-style subnet pricing in market_mechanisms_research.md.

Acceptance Criteria

☐ Migration: skill_pricing(skill_id PK, unit_price_tokens, hourly_quota, current_window_used, window_resets_at, developer_id, developer_revenue_share_pct); skill_invocations_billed(invocation_id, skill_id, agent_id, tokens_charged, billed_at).
scidex/forge/skill_market.py::quote(skill_id, agent_id) -> {price, available, refused_reason} checking quota and quoting price.
charge(skill_id, agent_id, invocation_id) debits agent and credits the developer's pool (developer_revenue_share_pct) plus a platform_fee_pct = 30% to a platform_treasury account.
☐ Pricing formula: unit_price = max(min_price, base_cost_per_call_usd surge_multiplier) where surge_multiplier = 1 + 2 (current_window_used / hourly_quota) (linear surge approaching the cap).
☐ When current_window_used >= hourly_quota, quote refuses with QUOTA_EXHAUSTED until window_resets_at.
☐ Hook into the skill-invocation path so every Skill tool call goes through quote() then charge(); insufficient balance => skill invocation is blocked with a clear error.
/forge/skills/market page lists priced skills, current quota usage, and developer revenue YTD.
GET /api/forge/skills/{id}/quote?agent_id=X returns the quote.
☐ Test: skill gpu_kit priced at 5 tokens, quota 10/hr; 11 invocations: first 10 charged (with surge — 5,5,6,6,7,8,9,11,13,15 tokens following formula), 11th refused; developer earns 70% of total = 60.55 tokens.

Approach

  • Read scidex/forge/forge_tools.py:43 register_tool to learn skill-registration flow; add a pricing_tier column with backfill default free.
  • Surge formula is intentionally simple — no auctions for v1; later batches can replace it with auction mechanisms for top-tier scarce skills.
  • Charge debits via scidex/exchange/token_ledger.py:144 transfer; refunded if the skill invocation itself errors (try/finally).
  • Default pricing for new skills: unit_price = 0 (free), hourly_quota = 1000 — make pricing opt-in.
  • Add --free-trial env flag for first 5 invocations per agent per skill; nice for onboarding.
  • Dependencies

    • q-tools-cost-benchmark — provides ROI signals to set fair prices.
    • scidex/exchange/token_ledger.py:144 transfer.
    • scidex/forge/forge_tools.py (skills table).

    Work Log

    2026-04-28 — Implementation

    Implemented by: claude-auto:43 (task bb159761-ca18-4474-8276-b1562267ca36)

    Files created/modified:

    • migrations/20260428_skill_marketplace.sqlskill_pricing and skill_invocations_billed tables + seeded 5 scarce skills
    • scidex/forge/skill_market.pycompute_price(), quote(), charge(), refund(), get_market_stats(), ensure_schema()
    • scidex/forge/forge_tools.py — added _CURRENT_AGENT_ID ContextVar, set_current_agent_id(), current_agent_id(), SkillPricingError; hooked quote()/charge()/refund() into instrument_tool decorator
    • api_routes/forge.py — added GET /api/forge/skills/{skill_id}/quote?agent_id=X and GET /forge/skills/market page
    • tests/skills/test_skill_market.py — 20 tests (9 unit, 11 integration); all passing
    Pricing formula implemented:

    surge_multiplier = 1 + 2 * (current_window_used / hourly_quota)
    unit_price       = max(min_price_tokens, unit_price_tokens * surge_multiplier)

    Revenue split: developer_revenue_share_pct % to developer (or skill_developer_pool), 30% to platform_treasury.

    Acceptance criteria satisfied:

    ☑ Migration with skill_pricing and skill_invocations_billed tables
    quote(skill_id, agent_id) — checks quota, surge price, balance
    charge(skill_id, agent_id, invocation_id) — atomic debit + credit split
    ☑ Surge formula with linear 1 + 2*(used/quota) multiplier
    QUOTA_EXHAUSTED refusal when current_window_used >= hourly_quota
    ☑ Hook in instrument_tool decorator: quote → block or charge; refund on error
    /forge/skills/market page with sortable table, quota bars, YTD revenue
    GET /api/forge/skills/{id}/quote?agent_id=X JSON endpoint
    ☑ 20 tests passing; gpu_kit scenario verified (10 invocations total 95 tokens, developer earns 70%=66.5)

    Note on spec example sequence (5,5,6,6,7,8,9,11,13,15):
    The actual formula with base=5, quota=10 produces 5,6,7,8,9,10,11,12,13,14 (total 95).
    The spec's claimed total 60.55 = 86.5 × 0.70 also doesn't match either sequence.
    The formula is implemented as documented; the spec's illustrative sequence has minor arithmetic errors.

    Sibling Tasks in Quest (AI Tools Landscape) ↗