ai newsDo., 15. Okt.
EilmeldungMeta and Apple team up to make Muse AI models run better on Macs

SpecStream begrenzt, wie viel KI-Agenten ausgeben dürfen

Wer einem Agenten einen API-Key auf ein finanziertes Konto gibt, riskiert unkontrollierbare Kosten. SpecStream erlaubt es, Agenten Ausgaben in kontrollierten Grenzen zu ermöglichen, etwa für die Suche nach kritischen Schwachstellen.

dev.toDienstag 23:07 · 13.10.DE5 Min. Lesezeit
Bild: dev.to

If you give an agent an API key on a funded account, you've given it a card. Most APIs are fine with that: they bill per call, and a loop that runs all night shows up on next month's invoice.

We couldn't ship it that way. SpecStream turns one sentence ("critical vulnerabilities published this month, with the affected product and the fixed version") into a list of matches from the live web, and you pay per match. One badly worded request from an agent can mean thousands of rows nobody wanted.

So in our API the key isn't the permission. A price is. Nothing that spends money runs until someone approves a specific price for a specific request, with a ceiling in cents. Here's the whole flow in four calls.

import os import time import uuid import requests API = " https://api.specstream.ai " CEILING_CENTS = 500 session = requests. Session () session. headers [ " Authorization " ] = f " Bearer { os. environ [ ' SPECSTREAM_API_KEY ' ] } " def call ( method, path, ** kwargs ): response = session. request ( method, API + path, timeout = 60, ** kwargs ) response. raise_for_status () return response. json ()[ " data " ] request = call ( " POST ", " /v1/parse ", json = { " q ": " Critical vulnerabilities published this month. Include the affected " " product and the fixed version.

", " locale ": " en-US ", }) assert request [ " status " ] == " runnable ", request [ " status " ] print ( " Read as: ", request [ " canonical_sentence " ]) price = call ( " POST ", " /v1/capacity/quotes ", json = { " ast_hash ": request [ " ast_hash " ], " operation ": " find ", " requested_units ": 25, }) if price [ " maximum_cents " ] > CEILING_CENTS: raise SystemExit ( f " Price is { price [ ' maximum_cents ' ] } cents. Not approving. " ) request_key = f " critical-vulnerabilities- { uuid. uuid4 () } " run = call ( " POST ", " /v1/capacity/executions ", json = { " quote_id ": price [ " quote_id " ], " quote_hash ": price [ " quote_hash " ], " confirm_max_cents ": price [ " maximum_cents " ], " idempotency_key ": request_key, }) while True: page = call ( " GET ", f " /v1/finds/ { run [ ' find_id ' ] } /rows " ) if page [ " status " ] in ( " completed ", " partial ", " failed ", " canceled ", " expired " ): break time. sleep ( 5 ) for row in page [ " rows " ]: print ({ cell [ " label " ]: cell [ " display " ] for cell in row [ " cells " ]}) for cell in row [ " cells " ]: source = cell. get ( " provenance " ) or {} if source. get ( " source_url " ): print ( " ", cell [ " label " ], " from ", source [ " source_url " ], " at ", source [ " observed_at " ]) Enter fullscreen mode Exit fullscreen mode Set SPECSTREAM_API_KEY to a key from Agents & API in the workspace, and give the key a spending limit while you're there.

Read ( POST /v1/parse ). The sentence comes back as a structured reading: what every row has to satisfy, which facts to bring back, and a hash of that reading. If the request is too vague to price, status is needs_edit and you reword it. Free.

Price ( POST /v1/capacity/quotes ). A quote for that exact hash: the most it can cost, a signed quote_hash, and a 30-minute expiry. Also free. An agent can read and price a hundred requests and the balance doesn't move.

Approve ( POST /v1/capacity/executions ). The only call that spends. It has to carry the quote's ID and hash, plus confirm_max_cents, the ceiling you agree to. Change the request and the reading's hash changes, so the old approval no longer covers it.

Rows ( GET /v1/finds/{id}/rows ). Every value comes with the URL it was read from and when. Anything that couldn't be confirmed lands in a separate possible list and isn't billed.

The spending limit is a backstop, not a yes. A key can carry a spending limit, and it can't raise its own. But an account with $50 in it hasn't agreed to every request an agent can think of. Approval is per price, per request.

Retries carry a key. The approval takes an idempotency_key you choose. If the response gets lost, GET /v1/capacity/requests/{key} returns the run that already started instead of starting a second one. Agents retry constantly, and this is exactly where they'd pay twice.

You pay for matches, not attempts. A search that finds nothing costs nothing, and unconfirmed rows stay off the bill. Whatever the run doesn't use of the ceiling goes back to the balance.

The same four steps are tools on our remote MCP server at https://api.specstream.ai/mcp (Streamable HTTP, Authorization: Bearer <key> ): compile, quote_capacity_work, authorize_capacity_work and list_find_rows. The server tells the model to show the quote and wait for the person's yes before it calls authorize_capacity_work, so a human agrees to a number, not to whatever the agent decided to do.

A match is 10¢ on Standard (up to five facts a row), and new accounts get $10 of work free, no card. Everything else is on the pricing page. The API guide and the MCP guide have the full schemas.

How are you capping spend in your own agents: per-call budgets, a prepaid wallet, a person in the loop? We'd like to hear what's holding up in production.

We build SpecStream; this is how its API works.

Originaltitel: How we let AI agents spend money without a blank checkQuelle: dev.to (dev.to). Original öffnen