Skip to content

Add Groq as a third delegate_agent provider option - #106

Merged
allocsys merged 17 commits into
mainfrom
feature/groq-provider
Aug 27, 2026
Merged

Add Groq as a third delegate_agent provider option#106
allocsys merged 17 commits into
mainfrom
feature/groq-provider

Conversation

@allocsys

Copy link
Copy Markdown
Owner

Adds Groq as a third delegate_agent provider option (provider: "groq"), alongside Gemini (default) and GLM.

Why: GLM/OpenRouter's free tier turned out to be gated by account credit balance (a zero-balance account is blocked from free models too, not just paid ones — see plan.md "Current status"). Groq's free tier is request/token-rate-limited instead, not tied to a dollar balance, and needs no credit card.

What's included (plan.md steps 1-8, all green in CI):

  • connectors/groq/client.js — OpenAI-compatible wire client, modeled on connectors/glm/client.js (same key/model cascade, cooldown-namespace pattern)
  • connectors/openai_shape/adapter.js — extracted from connectors/glm/adapter.js so GLM and Groq share one translation layer instead of duplicating it (glm/adapter.js now re-exports from here, so nothing importing the old path breaks)
  • connectors/llm/router.js — new groq branch in providerChat
  • connectors/gemini/agent_tools.js"groq" added to the provider zod enum + updated arg descriptions
  • Config: GROQ_API_KEYS, GROQ_MODEL (default openai/gpt-oss-120b, production), GROQ_FALLBACK_MODELS (default qwen/qwen3.6-27b, preview — kept as fallback only, see plan.md's "Model choice — CORRECTED" note), GROQ_REQUEST_TIMEOUT_MS, GROQ_DEFAULT_MAX_OUTPUT_TOKENS
  • Tests: test/groq-client.test.js, test/openai-shape-adapter.test.js (renamed from test/glm-adapter.test.js), groq coverage added to test/llm-router.test.js and test/agent-delegate-loop.test.js
  • Docs: README.md, docs/API_KEYS.md, docs/env.html all updated to cover GROQ_API_KEYS and the new provider option (these were missed in the initial implementation pass and caught/fixed afterward)

Cooldown (connectors/gemini/cooldown.js) and checkpoint (connectors/gemini/agent_checkpoint.js) needed no changes — both were already provider-agnostic, confirmed by direct read rather than assumed.

Rollout: ship behind provider: "groq", opt-in only — DEFAULT_LLM_PROVIDER stays "gemini". GLM/OpenRouter code path is untouched and will resume working immediately if OpenRouter credit is ever added.

Not yet done (tracked in plan.md, step 9): a live smoke test against a real Groq account. Everything here is only exercised against mocked fetch/providerChat calls — nothing has hit api.groq.com yet, so the max_tokens vs max_completion_tokens question flagged in GROQ_DEFAULT_MAX_OUTPUT_TOKENS's comment, and whether Groq's free tier is genuinely not balance-gated (an assumption, not yet confirmed against this account), are both still open. Requires GROQ_API_KEYS to be set to verify.

…, GROQ_FALLBACK_MODELS, GROQ_REQUEST_TIMEOUT_MS, GROQ_DEFAULT_MAX_OUTPUT_TOKENS). Model defaults per plan.md's corrected choice: openai/gpt-oss-120b (production) primary, qwen/qwen3.6-27b (preview, benchmark-strong but liable to disappear) as fallback only. GROQ_DEFAULT_MAX_OUTPUT_TOKENS set up front this time (unlike GLM_DEFAULT_MAX_OUTPUT_TOKENS, which was only added after a live 402) -- flagged in comments as unverified against Groq's actual param-name/limit behavior until the live smoke test in step 9.
…-shape translation into a shared connectors/openai_shape/adapter.js, so Groq (another OpenAI-compatible provider) doesn't get a duplicate copy of the same three functions. Content is a verbatim move (no logic changes) -- glm/adapter.js becomes a thin re-export in the next commit to preserve existing imports/tests.
… thin re-export of the newly-extracted connectors/openai_shape/adapter.js. Preserves the existing import path (../glm/adapter.js) for any code/tests that still reference it -- test/glm-adapter.test.js keeps passing unchanged since the functions it imports still exist at the same path, just forwarded.
…mpatible wire client modeled closely on connectors/glm/client.js. Key differences from GLM: single-vendor endpoint (no OpenRouter-style headers needed), error/message strings say "Groq" not "OpenRouter", and env var names are GROQ_* throughout. Cascade shape (outer over GROQ_API_KEYS on 401/403/429, inner over GROQ_MODEL + GROQ_FALLBACK_MODELS on 429/503/transient) and cooldown-namespace pattern (groq:${keyIndex}) are unchanged from GLM's client, reusing the same connectors/gemini/cooldown.js module (already provider-agnostic).
…the existing "glm" branch (same adapter reuse, same "explicit maxOutputTokens wins, otherwise apply the provider's own default" contract). Also switches the adapter import to the new shared connectors/openai_shape/adapter.js path (previously ../glm/adapter.js, which still re-exports the same functions -- see that file's step-3 commit -- but importing from the canonical shared module directly is clearer now that two providers depend on it).
…m (zod enums don't silently accept unlisted values, so this was a required change, not optional). Updated the provider/model/maxOutputTokens descriptions to mention Groq alongside Gemini/GLM.
…lm-client.test.js's coverage (key/model cascade, cooldown skip, bad-key rotation, explicit-model cascade-disable, network/abort transient mapping, no-choices error). Groq has no OpenRouter-style key-switch-on-401/403-only distinction to worry about differently -- same cascade rules apply, just against GROQ_* config and "Groq API error" message strings instead of "OpenRouter API error".
…m ../connectors/glm/adapter.js to ../connectors/openai_shape/adapter.js (matching router.js's new import, see the router.js commit) and add groq dispatch coverage mirroring the existing glm tests -- dispatch/adapter-reuse, tools-omitted contract, explicit maxOutputTokens override, and failure propagation.
…ovider parametrization. providerChat is fully mocked in this file, so runInvestigation's loop behaviors (stuck-loop guard, step-budget, checkpoint resume) are provider-invariant by construction -- this just confirms that invariant actually holds for a third provider value, not only two.
…-shape-adapter.test.js and repoint its import at the new shared connectors/openai_shape/adapter.js module, matching where the implementation actually lives now. Avoids running the same coverage twice under two names (glm/adapter.js is now just a re-export, so testing through it again would be redundant, not additional protection).
…ference connectors/openai_shape/adapter.js instead of connectors/glm/adapter.js -- no assertion logic changed, this is purely the rename's follow-through.
… remaining work (live smoke test, docs) before rollout. Add missing "Model choice -- CORRECTED" note that config.js/commit 8bb2f4f already reference but this doc never actually recorded.
…ded in commit 8bb2f4f) and that commit's own message already reference, but this plan doc never actually recorded -- the qwen/gpt-oss ordering below was superseded before implementation and the shipped code uses the opposite ordering.
…ag 9-10 as the remaining work, so the plan doc matches the branch's actual state instead of reading as "not started".
…der implementation pass) -- mirrors the OPENROUTER_API_KEYS card's multi-key pattern, and updates the fill-count total from 14 to 15.
…implementation pass, see plan.md STATUS): mention it alongside Gemini/GLM in delegate_agent's description, add a key badge, and add GROQ_* rows to the config table.
@allocsys
allocsys merged commit 599117b into main Aug 27, 2026
2 checks passed
@allocsys
allocsys deleted the feature/groq-provider branch August 27, 2026 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant