feat: add Volcengine Ark (火山引擎) as built-in provider - #52836
feat: add Volcengine Ark (火山引擎) as built-in provider#52836david-bowiegxw wants to merge 3 commits into
Conversation
Adds Volcengine Ark — ByteDance's unified model platform — as a built-in provider, discoverable from Settings → Providers (paste ARK_API_KEY). - Anthropic-compatible /api/coding endpoint (api_mode=anthropic_messages) so prompt caching works automatically. - Overrides fetch_models() to return the maintained Agent Plan text-model list; Ark's /models endpoint otherwise returns a large stale catalog. - Aliases: ark, volcengine, volcano, bytedance. Closes NousResearch#29331 Closes NousResearch#40195 Closes NousResearch#51319
57741fd to
d0e67d0
Compare
…o caching-capable doubao-seed-2.0-lite Measured prompt-caching support on Ark /api/coding per model (8/11 cache, with per-model prefix thresholds 4k-48k; flash/kimi-k2.6/minimax-m2.7 do not). default_aux_model was deepseek-v4-flash which never caches, so aux calls re-bill the full prefix every time; switch to doubao-seed-2.0-lite (cheapest caching model, ~4k threshold).
…odels anthropic_prompt_cache_policy() only auto-enables caching for third-party Anthropic gateways when the model is Claude-named (is_anthropic_wire and is_claude). Ark speaks the native Anthropic protocol on /api/coding but serves non-Claude families (deepseek-v4, glm-5.2, doubao-seed, kimi-k2, minimax-m3), so it fell through to (False, False) — 0% cache hits, re-billing the full prompt every turn. Same class as NousResearch#17332 (MiniMax's own models); fixed the same way with an explicit allowlist branch under the is_anthropic_wire gate, returning (True, True) for native Anthropic layout. Bundled into this provider PR so adopting Ark gives complete support (routing + caching) in one change; routing depends on the resolver fix in NousResearch#53055. - agent/agent_runtime_helpers.py: add Ark provider/host branch. - tests: TestVolcengineArkAnthropicWire (4 cases incl. OpenAI-wire negative). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@teknium1 — Ark (火山引擎 / Doubao) is still one of the few major providers not built-in, and I've kept this current. Two notes after 0.18.0: 1. Still needed. 2. Happy to make this trivial to take. I can fold the provider (#52836) + the small resolver fix (#53055) into a single PR rebased onto current main — same shape as the Vertex salvage in #56363 — so there's one thing to review. It closes the three standing requests (#29331, #40195, #51319) and consolidates the earlier bundled attempts (#8952, #14070, #32549) into one focused, plugin-native provider. Ark's |
|
+1 on this |
|
Thanks for the focused provider implementation and the detailed endpoint/cache investigation. This automated hermes-sweeper review is closing this as not planned under the
Please publish Ark as a standalone model-provider plugin repository for installation under Closed as not planned per standing maintainer policy ( Closed as not-planned per standing maintainer policy ( |
|
@teknium1 — replying under the escalation path in the close notice ("If you believe this policy was misapplied to your change, comment here and a maintainer will take a look"). I believe 1. The policy's own text doesn't cover model providers. The June 2026 policy (added in #54001, 2026-06-27) enumerates "observability/metrics backends, vendor SaaS connectors, analytics dashboards, paid-service tie-ins" under 2. Post-policy merge practice confirms that reading. After the policy landed, two new third-party provider directories were merged in-tree: Vertex AI (#56363, 2026-07-01) and Fireworks AI (c97d9a4, 2026-07-08). Fireworks is a third-party commercial inference vendor — exactly this PR's category. 3. The cited precedent is the same sweeper batch, not standing practice. #29331 (closed 07-13) and #40195 (closed 07-14) were closed by the same automated review in the same three-day window as this PR (07-15). The third standing request, #51319, is still open. 4. Ark isn't a niche backend. Volcengine Ark holds 49.5% of China's public-cloud MaaS market (IDC, 2025 full-year — vs. Alibaba Cloud 27%, Baidu 17%), serving 180T+ tokens/day as of June 2026 (IDC via 36kr). Like OpenRouter, it fronts third-party models (DeepSeek, GLM, Kimi, MiniMax) behind one API. The tree already ships its direct peers: 5. The policy's stated rationale — maintenance load — actually cuts the other way here. Users already run Ark through If the considered call going forward is that new model providers should also ship standalone, I'll happily publish it that way — but that would be a new policy beyond the current AGENTS.md text and recent merge practice, so I'd ask for a human look before this close stands. Meanwhile I'm addressing the review on #53055 (declared-profile fallback across all three API-key resolver paths + a full discovery→registration→resolve regression test), which this provider depends on for correct Could this be reopened pending that look? |
|
I'm in strong agreement with @david-bowiegxw's escalation — the On the policy itself: For what it's worth, I've hit the same wall maintaining a provider in this tree. I work on the Z.AI / GLM (智谱) provider, and two of those PRs were closed without merging:
So even an already-peered vendor's models stall on the in-tree path regardless of code quality. Reopening this (or at minimum carving |
|
Adding a documentation follow-up to my comment above, since I went and read the actual guidance. I pulled the current The June 2026 "third-party-product" policy (AGENTS.md 797–813, mirrored at CONTRIBUTING.md 88–101) lists exactly:
It does not name model providers. Immediately below it, AGENTS.md 815+ "### Model-provider plugins (
and its scan order puts So the doc simultaneously says (a) "third-party products don't land in-tree" and (b) "every inference backend — including third-party ones like deepseek, minimax, kimi — ships as a plugin here, bundled in-tree." Volcengine Ark is both a "third-party product" and an "inference backend," and the sweeper applied only (a). That's the misapplication in one screenshot: the policy paragraph never covered model providers, while the model-provider paragraph three lines down explicitly blesses the in-tree bundled form. This isn't a judgment on code quality (the close notice says as much) — it's that the automation read the June policy paragraph and skipped the model-provider paragraph right beneath it. Carving |
|
Small maintenance update on this branch ( Re-verified all 11 hardcoded model IDs live against Flagging mainly as a liveness signal: the vendor's model lineup keeps shifting (this is the second such churn since the PR opened), which is exactly the kind of upkeep an in-tree provider absorbs on behalf of users rather than leaving to a fork nobody watches. Still hoping for a look at the reopen request above whenever you get a chance. |
Summary
Adds Volcengine Ark (火山引擎) — ByteDance's unified AI model platform — as a first-class built-in provider. Users can discover and configure it directly from Settings → Providers.
What's included
plugins/model-providers/volcengine-ark/__init__.py—ProviderProfilesubclass +plugin.yamlmanifest/api/codingendpoint viaapi_mode="anthropic_messages"fetch_models()to return the maintained text-model list (11 models)ark,volcengine,volcano,bytedanceagent/agent_runtime_helpers.py— prompt-caching enablement so adopting Ark gives complete support (routing + caching) in one changeis_claudegate inanthropic_prompt_cache_policy()excluded it → 0% cache hits, re-billing the full prefix every turnTestVolcengineArkAnthropicWire(4 cases) intests/run_agent/test_anthropic_prompt_cache_policy.pyValidated end-to-end (real measurements, not just code)
I ran this against a live Ark subscription through the actual Hermes CLI, not only as a unit. Sharing the results because they're useful feedback on Ark's behavior regardless of whether this exact PR lands.
Discovery + registration: loaded under Hermes' runtime, the provider is discovered as
volcengine-ark,VolcengineArkProfileinstantiates with the right fields, andfetch_models()returns the 11 hardcoded models. ✅Prompt caching — measured per model. Ark's
/api/codingendpoint speaks the Anthropic Messages protocol, so I sent an identicalcache_control-marked prefix twice per model and readusage.cache_read_input_tokens, sweeping prefix sizes 4k→64k tokens (2026-06-26):/api/codingdeepseek-v4-proglm-5.2doubao-seed-2.0-litekimi-k2.7-codeminimax-m3doubao-seed-2.0-minidoubao-seed-2.0-codedoubao-seed-2.0-prodeepseek-v4-flashkimi-k2.6minimax-m2.7Two findings worth knowing:
doubao-seed-2.0-litereturned 0 at one size and cached at others. This matches Ark's own docs (隐式缓存「不保证命中,分布式路由影响命中概率」) and diverges from Anthropic's deterministiccache_controlguarantee — worth flagging for anyone relying on cache behavior here. Note this is Ark's/api/codingsurface; Ark also has separate/api/v3implicit and/api/v3/contextexplicit caching with different model support.Aux model:
default_aux_modelwasdeepseek-v4-flash, which never caches — so high-frequency background tasks (titles, compression) re-bill the full prefix every call. Switched todoubao-seed-2.0-lite, the cheapest model that caches and at the lowest prefix threshold.This PR wires the emission, not just measures it: the
anthropic_prompt_cache_policy()Ark branch (see "What's included") makes Hermes actually send thecache_controlmarkers. Without it Ark's non-Claude models hit theis_claudegate and get 0% caching even when routed correctly.Prerequisite: resolver fix in #53055 (separate PR)
In the interest of honest feedback: as a pure 2-file plugin this provider 404s at runtime without a one-time framework fix, which is now in its own PR — #53055 (issue #53054). Root cause is a real gap in the runtime resolver, not in this plugin:
_resolve_runtime_from_pool_entry(hermes_cli/runtime_provider.py) derivesapi_modefor a selected provider from config or from_detect_api_mode_for_url(base_url). TheProviderProfile.api_modedeclared by a plugin is dropped at the bridge —ProviderConfig(hermes_cli/auth.py) had noapi_modefield._detect_api_mode_for_urlrecognizesanthropic_messagesonly for/anthropicpaths andapi.kimi.com+/coding. Ark'sark.cn-beijing.volces.com+/api/codingmatches neither, so it silently falls back tochat_completions→ posts OpenAI-style/chat/completionsto Ark's Anthropic-only endpoint → nginx 404.Note this is not "the first
anthropic_messagesplugin" — MiniMax is one too. MiniMax only avoids the bug by coincidence: itsbase_urlends in/anthropic, so the URL heuristic re-derives the right mode and its declaredapi_modefield is never actually read. Ark's/api/codingendpoint isn't URL-self-describing, so it's the first to expose that the declaration is dropped. #53055 makes the declaration authoritative for any such plugin (additive, non-regressing, with tests). This provider PR depends on #53055.Design decisions
anthropic_messagesprotocol — Ark's/api/codingendpoint speaks the Anthropic Messages API and supports prompt caching (validated above); the OpenAI-protocol path on Ark exposes the Responses API, which Hermes doesn't use. AProviderProfiledeclares a singleapi_mode, so we default to the one that gives Hermes caching.base_url, API key, protocol, and model IDs; they differ only in Volcengine-side billing/quota, which the client can't and shouldn't detect. So this is a single provider entry rather than two near-identical profiles (unlikealibabavsalibaba-coding-plan, which hit different endpoints)./modelsendpoint returns a large stale catalog rather than the user's active models, sofetch_models()is overridden to return the current maintained list (update when Ark's lineup changes).tips.pyor unrelated edits). The requiredapi_moderesolver wiring lives in its own PR (fix(providers): gate plugin api_mode by endpoint (#53054) #53055), not here, so this PR stays a self-contained plugin.Relation to prior attempts
Volcengine Ark has been requested repeatedly and attempted several times, but no prior PR has landed. This one differs by being the only single-focus implementation built on the current pluggable
plugins/model-providers/architecture (which postdates those PRs):hermes_cli/auth.py,main.py,gateway/run.py,model_metadata.py); predates the pluggable-provider refactor; bundles BytePlus.hermes_cli/core (ark_providers.py,model_setup_flows.py,providers.py); does not use theplugins/model-providers/mechanism; bundles BytePlus.By contrast this PR is a self-contained
ProviderProfileplugin (2 files) scoped to Volcengine Ark only, plus the small resolver wiring noted above. Happy to consolidate the older PRs into this one if maintainers prefer.Related issues