商业产业 Hacker News Agent 2026-07-15T15:51 正文 ok 688 words

🔶 Launch HN:Coasty (YC S26) – 一个面向计算机使用代理的 API

英文标题:🔶 Launch HN: Coasty (YC S26) – An API for computer-use agents

Coasty(YC S26)推出了 BYOK(自带密钥)功能,允许开发者使用自己的 Anthropic 或 OpenAI API 密钥来驱动计算机使用代理,而不再依赖平台托管模型。密钥可通过 AES-256-GCM 加密存储或请求头传入,永远不会在运行日志或 Webhook 中回显,显著提升安全性与数据主权。平台还支持按代理角色指定不同模型,以便平衡成本与质量,并承诺绝不静默回退到平台密钥。这对注重合规、成本控制与厂商中立的开发团队具有直接价值。
打开原文相关 5 · 机会 3
media17.6 KB

中文

默认情况下,computer-use harness 中的所有 LLM 调用都在 Coasty 的托管模型上运行。BYOK(自带密钥)翻转了这一模式:选择加入后,整个 harness(包括 worker、grounding、代码代理和 compaction;即每一次 LLM 调用)都将改为在你自己的 Anthropic 或 OpenAI 账户上运行。选择加入始终是显式的,可以按请求或按存储的密钥指定。provider: "managed"(或完全省略 llm)将保持平台默认值,不作任何改变。

有两种方式提供密钥。你可以通过 PUT /v1/llm/keys/{provider} 一次性存储密钥(静态加密,使用 AES-256-GCM;仅回显 sha256 前缀指纹),也可以在每个请求的请求头中传入密钥。请求头中的密钥优先级高于存储的密钥。只发送密钥而未指定提供商将返回 422。

X-LLM-Provider: anthropic X-LLM-Api-Key: sk-ant-your_key_here X-LLM-Model: claude-sonnet-4-6

这些请求头适用于 POST /v1/predict、POST /v1/runs、POST /v1/workflows/{id}/runs、POST /v1/sessions 和 POST /v1/schedules。存储的密钥通过三个端点管理,受 llm_keys 作用域保护(默认授予新创建的生产密钥)。这些端点需要使用生产密钥;沙箱密钥无法读取、覆盖或删除生产凭证存储:

python import os, requests

BASE = "https://coasty.ai/v1" HEADERS = {"X-API-Key": os.environ["COASTY_API_KEY"]}

Store (upsert) your own Anthropic key. Encrypted at rest; never echoed back.

stored = requests.put( f"{BASE}/llm/keys/anthropic", headers=HEADERS, json={"api_key": os.environ["ANTHROPIC_API_KEY"]}, timeout=30, ).json() print(stored) # {"provider": "anthropic", "key_fingerprint": "a1b2c3d4", "stored": true}

List stored keys: provider, fingerprint, timestamps. Never the key itself.

keys = requests.get(f"{BASE}/llm/keys", headers=HEADERS, timeout=30).json() for k in keys["keys"]: print(k["provider"], k["key_fingerprint"])

Delete when you rotate away (404 LLM_KEY_NOT_FOUND when none is stored)

requests.delete(f"{BASE}/llm/keys/anthropic", headers=HEADERS, timeout=30)

在请求体中,相同的端点接受一个 llm 对象,用于选择提供商,并可选择按 harness 角色指定模型。该对象有意不包含 api_key 字段(若尝试添加会返回 422):密钥仅通过请求头或加密存储传递,因此永远不会在运行对象、Webhook 或幂等重放中被回显。

python import os, requests

BASE = "https://coasty.ai/v1" HEADERS = {"X-API-Key": os.environ["COASTY_API_KEY"]}

Start a run on YOUR Anthropic key (stored earlier via PUT /llm/keys/anthropic).

The llm block deliberately has NO api_key field (422 if you try): keys ride

headers or the encrypted store only, never request bodies.

run = requests.post( f"{BASE}/runs", headers=HEADERS, json={ "machine_id": "mch_test_0123456789abcdef", "task": "Open the billing page and download the latest invoice as PDF", "llm": { "provider": "anthropic", # or "openai"; "managed" = platform default "model": "claude-sonnet-4-6", # any model on your account (vision-capable) "compaction_model": "claude-haiku-4-5", # optional per-role override }, }, timeout=30, ).json()

Per-request variant: send the key in headers instead of storing it.

A header key takes precedence over the stored key for this request only.

byok_headers = { **HEADERS, "X-LLM-Provider": "anthropic", "X-LLM-Api-Key": os.environ["ANTHROPIC_API_KEY"], "X-LLM-Model": "claude-sonnet-4-6", }

The run echoes a non-secret llm block; the key itself is never returned.

run = requests.get(f"{BASE}/runs/{run['id']}", headers=HEADERS, timeout=30).json() print(run["llm"]) # {"provider": ..., "model": ..., "key_fingerprint": ..., "key_source": ..., "key_scrubbed": ...}

按角色覆盖可用于在成本与质量之间进行调优:例如,在 compaction 上使用较便宜的模型,而 worker 保持默认。对于运行、工作流和计划,密钥会以加密快照形式存入运行,以确保在副本崩溃恢复后继续使用你的密钥;一旦运行到达终态,密钥即被擦除。GET /v1/runs/{id} 回显一个非机密的 llm 块:{provider, model, key_fingerprint, key_source, key_scrubbed}。计划仅存储非机密偏好;触发时使用当前已存储的密钥。删除存储的密钥后,未来的触发会明确失败并返回 LLM_KEY_NOT_CONFIGURED;它们绝不会静默在平台密钥上运行。

Grounding(像素坐标解析)质量已在平台模型上调优。当在你自己的模型上运行 grounding 时,使用默认设置可获得最佳效果,并可在正式切换到更便宜或不同的模型之前,通过 grounding_model 进行实验。

绝不静默回退:一旦你请求 BYOK,任何代码路径都不能使用 Coasty 的平台 LLM 密钥。来自你的提供商的错误会作为与你密钥相关的问题直接暴露,并提供稳定的错误码:LLM_KEY_NOT_CONFIGURED、LLM_KEY_INVALID、LLM_PROVIDER_AUTH_FAILED、LLM_PROVIDER_RATE_LIMITED、LLM_PROVIDER_QUOTA_EXCEEDED 和 LLM_PROVIDER_ERROR。

计费:使用 BYOK 时,Coasty 对每次调用和每个步骤的平台收费保持不变。模型 Token 直接由你的提供商账户计费。

English / 原文

By default every LLM call in the computer-use harness runs on Coasty's managed models. BYOK (bring your own key) flips that: opt in and the entire harness (the worker, grounding, the code agent, and compaction; every LLM call) runs on your own Anthropic or OpenAI account instead. Opt-in is always explicit, per request or per stored key. provider: "managed" (or omitting llm entirely) keeps the platform default, unchanged.

There are two ways to hand over a key. Store it once with PUT /v1/llm/keys/{provider} (encrypted with AES-256-GCM at rest; only a sha256-prefix fingerprint is ever echoed back), or send it per request in headers. A header key takes precedence over the stored key. Sending a key without a provider returns 422.

X-LLM-Provider: anthropic
X-LLM-Api-Key: sk-ant-your_key_here
X-LLM-Model: claude-sonnet-4-6

The headers work on POST /v1/predict, POST /v1/runs, POST /v1/workflows/{id}/runs, POST /v1/sessions, and POST /v1/schedules. Stored keys are managed through three endpoints, gated by the llm_keys scope (granted to new live keys by default). These endpoints require a live key; sandbox keys cannot read, overwrite, or delete the production credential store:

import os, requests

BASE = "https://coasty.ai/v1"
HEADERS = {"X-API-Key": os.environ["COASTY_API_KEY"]}

# Store (upsert) your own Anthropic key. Encrypted at rest; never echoed back.
stored = requests.put(
    f"{BASE}/llm/keys/anthropic",
    headers=HEADERS,
    json={"api_key": os.environ["ANTHROPIC_API_KEY"]},
    timeout=30,
).json()
print(stored)   # {"provider": "anthropic", "key_fingerprint": "a1b2c3d4", "stored": true}

# List stored keys: provider, fingerprint, timestamps. Never the key itself.
keys = requests.get(f"{BASE}/llm/keys", headers=HEADERS, timeout=30).json()
for k in keys["keys"]:
    print(k["provider"], k["key_fingerprint"])

# Delete when you rotate away (404 LLM_KEY_NOT_FOUND when none is stored)
requests.delete(f"{BASE}/llm/keys/anthropic", headers=HEADERS, timeout=30)

On the request body, the same endpoints accept an llm object that selects the provider and, optionally, a model per harness role. It deliberately has no api_key field (a 422 if you attempt one): keys ride headers or the encrypted store only, so they can never be echoed in run objects, webhooks, or idempotency replays.

import os, requests

BASE = "https://coasty.ai/v1"
HEADERS = {"X-API-Key": os.environ["COASTY_API_KEY"]}

# Start a run on YOUR Anthropic key (stored earlier via PUT /llm/keys/anthropic).
# The llm block deliberately has NO api_key field (422 if you try): keys ride
# headers or the encrypted store only, never request bodies.
run = requests.post(
    f"{BASE}/runs",
    headers=HEADERS,
    json={
        "machine_id": "mch_test_0123456789abcdef",
        "task": "Open the billing page and download the latest invoice as PDF",
        "llm": {
            "provider": "anthropic",             # or "openai"; "managed" = platform default
            "model": "claude-sonnet-4-6",        # any model on your account (vision-capable)
            "compaction_model": "claude-haiku-4-5",  # optional per-role override
        },
    },
    timeout=30,
).json()

# Per-request variant: send the key in headers instead of storing it.
# A header key takes precedence over the stored key for this request only.
byok_headers = {
    **HEADERS,
    "X-LLM-Provider": "anthropic",
    "X-LLM-Api-Key": os.environ["ANTHROPIC_API_KEY"],
    "X-LLM-Model": "claude-sonnet-4-6",
}

# The run echoes a non-secret llm block; the key itself is never returned.
run = requests.get(f"{BASE}/runs/{run['id']}", headers=HEADERS, timeout=30).json()
print(run["llm"])   # {"provider": ..., "model": ..., "key_fingerprint": ..., "key_source": ..., "key_scrubbed": ...}

Per-role overrides exist for tuning cost against quality: run compaction on a cheaper model while the worker stays on the default, for example. For runs, workflows, and schedules the key is snapshotted encrypted into the run, so crash-recovery on another replica keeps using your key; it is scrubbed the moment the run reaches a terminal state. GET /v1/runs/{id} echoes a non-secret llm block: {provider, model, key_fingerprint, key_source, key_scrubbed}. Schedules store only the non-secret preference; at fire time the current stored key is used. Delete the stored key and future firings fail loudly with LLM_KEY_NOT_CONFIGURED; they never silently run on platform keys.

Grounding (pixel-coordinate resolution) quality is tuned on the platform model. When running grounding on your own model, expect the best results with the defaults, and use grounding_model to experiment before committing a cheaper or different model to that role.

No silent fallback, ever: once you ask for BYOK, no code path can use Coasty's platform LLM keys. Errors from your provider surface as your key's issue with stable codes: LLM_KEY_NOT_CONFIGURED, LLM_KEY_INVALID, LLM_PROVIDER_AUTH_FAILED, LLM_PROVIDER_RATE_LIMITED, LLM_PROVIDER_QUOTA_EXCEEDED, and LLM_PROVIDER_ERROR.

Billing: Coasty's per-call and per-step platform charges are unchanged with BYOK. The model tokens are billed by your provider account directly.