Effort: thorough
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 scarce — optimize-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.
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.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).current_window_used >= hourly_quota, quote refuses with QUOTA_EXHAUSTED until window_resets_at.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.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.scidex/forge/forge_tools.py:43 register_tool to learn skill-registration flow; add a pricing_tier column with backfill default free.scidex/exchange/token_ledger.py:144 transfer; refunded if the skill invocation itself errors (try/finally).unit_price = 0 (free), hourly_quota = 1000 — make pricing opt-in.--free-trial env flag for first 5 invocations per agent per skill; nice for onboarding.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).Implemented by: claude-auto:43 (task bb159761-ca18-4474-8276-b1562267ca36)
Files created/modified:
migrations/20260428_skill_marketplace.sql — skill_pricing and skill_invocations_billed tables + seeded 5 scarce skillsscidex/forge/skill_market.py — compute_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 decoratorapi_routes/forge.py — added GET /api/forge/skills/{skill_id}/quote?agent_id=X and GET /forge/skills/market pagetests/skills/test_skill_market.py — 20 tests (9 unit, 11 integration); all passingsurge_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:
skill_pricing and skill_invocations_billed tablesquote(skill_id, agent_id) — checks quota, surge price, balancecharge(skill_id, agent_id, invocation_id) — atomic debit + credit split1 + 2*(used/quota) multiplierQUOTA_EXHAUSTED refusal when current_window_used >= hourly_quotainstrument_tool decorator: quote → block or charge; refund on error/forge/skills/market page with sortable table, quota bars, YTD revenueGET /api/forge/skills/{id}/quote?agent_id=X JSON endpointgpu_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.