ReactiveCleverAgentsApp has no credentials param, so non-native providers (openai_compatible) can never work through it #123

Closed
opened 2026-08-08 21:55:44 +00:00 by CoreRasurae · 0 comments
Member

Metadata

  • Commit Message: feat(application): support credential injection in ReactiveCleverAgentsApp
  • Branch: feature/application-credential-injection

Background and context

Discovered while investigating #121 and #122. Fixing both, in principle, could be as
simple as preferring ReactiveCleverAgentsApp — the library's documented "Quick start"
entry point (README.md) — over create_executor/Executor (documented separately in
docs/guides/reasoning-aware-llm-agents.md), since ReactiveCleverAgentsApp already
calls AgentFactory.validate_configuration() (core/application.py line 266, the fix
#122 asks for) and already resolves template:/agent_template: package references via
EnhancedTemplateRegistry (core/application.py lines 966-1004, the fix #121 asks for).

That option is blocked by a third, independent gap:
ReactiveCleverAgentsApp.load_configuration() constructs its internal AgentFactory
without a credentials argument at all —

self.agent_factory = AgentFactory(
    config_dict,
    self.template_renderer,
    stream_router=self.stream_router,
    langgraph_bridge=self.langgraph_bridge,
    skill_loader=skill_loader,
)

(core/application.py lines 247-253) — so every LLMAgent built through this path runs
in build_chat_model's "standalone / CLI mode" (agents/llm_client.py lines 31-58). Per
that function's own docstring: "Non-native providers raise ConfigurationError('Unsupported provider: ...')" when credentials is None. Any non-native provider — anything outside
openai/anthropic/google, per Actor Configuration Standard §4.4.1, including
openai_compatible pointed at a custom base_url — cannot be used through
ReactiveCleverAgentsApp at all, regardless of agent_template resolution: it fails
earlier and harder, with ConfigurationError: Unsupported provider: ..., than the bugs
in #121/#122.

Meanwhile, create_executor/Executor (the guide's documented entry point for exactly
this scenario — see docs/guides/reasoning-aware-llm-agents.md's own example, which
passes credentials={"openai_compatible": {"api_key": ..., "base_url": ...}} directly)
supports the opposite: AgentFactory.__init__'s credentials parameter enables
build_chat_model's "credential-injection mode" (ADR-2026), which is what makes a
non-native provider with a custom base_url work at all — but that path has no
agent_template/template resolution (#121) and no config validation (#122).

Net effect: the library's two documented public entry points have mutually exclusive
feature sets.
There is currently no way to get agent-template/package-reference
resolution, config validation, and non-native-provider credential injection in the same
run.

Current behavior

Constructing ReactiveCleverAgentsApp (per README.md's own "Quick start" example) with
a config file whose agent uses provider: openai_compatible and relies on a base_url
(rather than a literal api_key/native provider) fails with ConfigurationError: Unsupported provider: openai_compatible as soon as that agent is instantiated — there is
no way to supply credentials (api_key/base_url) for a non-native provider through
ReactiveCleverAgentsApp's public constructor or any other public method.

Expected behavior

ReactiveCleverAgentsApp should accept an optional credentials parameter (mirroring
create_executor's/Executor's existing credentials: dict[str, Any] | None) and thread
it into its internal AgentFactory construction, so that agents using non-native providers
(openai_compatible and similar, per Actor Configuration Standard §4.4.1) can resolve a
base_url/api_key the same way they already can via create_executor. This would let a
single code path (ReactiveCleverAgentsApp) support agent-template resolution (#121),
config validation (#122), and non-native-provider credential injection together.

Acceptance criteria

  • ReactiveCleverAgentsApp.__init__ accepts an optional credentials: dict[str, dict[str, str]] | None = None parameter.
  • load_configuration() forwards it to the internal AgentFactory(...) construction.
  • An agent with provider: openai_compatible and a credentials entry supplying
    api_key/base_url for that provider successfully constructs its chat model via
    run_single_shot()/start_interactive_session() (not just via create_executor()).
  • Existing standalone/CLI-mode behavior (no credentials supplied, native providers,
    or config-embedded api_key) is unchanged.
  • Tests (Behave): scenario constructing ReactiveCleverAgentsApp with credentials
    for a non-native provider and asserting successful single-shot execution against a
    stubbed/mocked chat model.

Supporting information

  • Related to, and discovered while investigating, #121 (agent-type package reference
    resolution missing from the Executor/AgentFactory path) and #122 (Executor never
    calls AgentFactory.validate_configuration()). Together, these three issues describe
    the full gap between the library's two documented entry points.
  • README.md "Quick start" (ReactiveCleverAgentsApp as the primary documented entry
    point) vs. docs/guides/reasoning-aware-llm-agents.md (create_executor, documented
    specifically for non-native-provider/credential-injection scenarios).
  • src/cleveractors/core/application.py lines 68-76 (ReactiveCleverAgentsApp.__init__
    signature — no credentials parameter), lines 236-253 (AgentFactory construction).
  • src/cleveractors/agents/llm_client.py lines 31-58 (build_chat_model docstring —
    explicit statement that standalone mode rejects non-native providers).
  • src/cleveractors/agents/factory.py (AgentFactory.__init__'s existing credentials
    parameter and ADR-2026 per-request credential injection, already used by
    create_executor).

Subtasks

  • Add credentials parameter to ReactiveCleverAgentsApp.__init__ and thread it
    through load_configuration() to AgentFactory(...).
  • Confirm AgentFactory's existing per-request credential-injection semantics
    (ADR-2026: skip caching when credentials are supplied) hold correctly when driven
    from this constructor path.
  • Tests (Behave): non-native-provider credential injection via
    ReactiveCleverAgentsApp.
  • Verify coverage >=97% via nox -s coverage_report.
  • Run nox (all default sessions), fix any errors.

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the
    Commit Message in Metadata exactly, followed by a blank line, then additional lines
    providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata
    exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged
    before this issue is marked done.
## Metadata - **Commit Message**: `feat(application): support credential injection in ReactiveCleverAgentsApp` - **Branch**: `feature/application-credential-injection` ## Background and context Discovered while investigating #121 and #122. Fixing both, in principle, could be as simple as preferring `ReactiveCleverAgentsApp` — the library's documented "Quick start" entry point (`README.md`) — over `create_executor`/`Executor` (documented separately in `docs/guides/reasoning-aware-llm-agents.md`), since `ReactiveCleverAgentsApp` already calls `AgentFactory.validate_configuration()` (`core/application.py` line 266, the fix #122 asks for) and already resolves `template:`/`agent_template:` package references via `EnhancedTemplateRegistry` (`core/application.py` lines 966-1004, the fix #121 asks for). That option is blocked by a third, independent gap: `ReactiveCleverAgentsApp.load_configuration()` constructs its internal `AgentFactory` without a `credentials` argument at all — ```python self.agent_factory = AgentFactory( config_dict, self.template_renderer, stream_router=self.stream_router, langgraph_bridge=self.langgraph_bridge, skill_loader=skill_loader, ) ``` (`core/application.py` lines 247-253) — so every `LLMAgent` built through this path runs in `build_chat_model`'s "standalone / CLI mode" (`agents/llm_client.py` lines 31-58). Per that function's own docstring: "Non-native providers raise `ConfigurationError('Unsupported provider: ...')`" when `credentials` is `None`. Any non-native provider — anything outside `openai`/`anthropic`/`google`, per Actor Configuration Standard §4.4.1, including `openai_compatible` pointed at a custom `base_url` — cannot be used through `ReactiveCleverAgentsApp` at all, regardless of `agent_template` resolution: it fails earlier and harder, with `ConfigurationError: Unsupported provider: ...`, than the bugs in #121/#122. Meanwhile, `create_executor`/`Executor` (the guide's documented entry point for exactly this scenario — see `docs/guides/reasoning-aware-llm-agents.md`'s own example, which passes `credentials={"openai_compatible": {"api_key": ..., "base_url": ...}}` directly) supports the opposite: `AgentFactory.__init__`'s `credentials` parameter enables `build_chat_model`'s "credential-injection mode" (ADR-2026), which is what makes a non-native provider with a custom `base_url` work at all — but that path has no `agent_template`/`template` resolution (#121) and no config validation (#122). **Net effect: the library's two documented public entry points have mutually exclusive feature sets.** There is currently no way to get agent-template/package-reference resolution, config validation, *and* non-native-provider credential injection in the same run. ## Current behavior Constructing `ReactiveCleverAgentsApp` (per `README.md`'s own "Quick start" example) with a config file whose agent uses `provider: openai_compatible` and relies on a `base_url` (rather than a literal `api_key`/native provider) fails with `ConfigurationError: Unsupported provider: openai_compatible` as soon as that agent is instantiated — there is no way to supply credentials (`api_key`/`base_url`) for a non-native provider through `ReactiveCleverAgentsApp`'s public constructor or any other public method. ## Expected behavior `ReactiveCleverAgentsApp` should accept an optional `credentials` parameter (mirroring `create_executor`'s/`Executor`'s existing `credentials: dict[str, Any] | None`) and thread it into its internal `AgentFactory` construction, so that agents using non-native providers (`openai_compatible` and similar, per Actor Configuration Standard §4.4.1) can resolve a `base_url`/`api_key` the same way they already can via `create_executor`. This would let a single code path (`ReactiveCleverAgentsApp`) support agent-template resolution (#121), config validation (#122), *and* non-native-provider credential injection together. ## Acceptance criteria - [ ] `ReactiveCleverAgentsApp.__init__` accepts an optional `credentials: dict[str, dict[str, str]] | None = None` parameter. - [ ] `load_configuration()` forwards it to the internal `AgentFactory(...)` construction. - [ ] An agent with `provider: openai_compatible` and a `credentials` entry supplying `api_key`/`base_url` for that provider successfully constructs its chat model via `run_single_shot()`/`start_interactive_session()` (not just via `create_executor()`). - [ ] Existing standalone/CLI-mode behavior (no `credentials` supplied, native providers, or config-embedded `api_key`) is unchanged. - [ ] Tests (Behave): scenario constructing `ReactiveCleverAgentsApp` with `credentials` for a non-native provider and asserting successful single-shot execution against a stubbed/mocked chat model. ## Supporting information - Related to, and discovered while investigating, #121 (agent-type package reference resolution missing from the `Executor`/`AgentFactory` path) and #122 (`Executor` never calls `AgentFactory.validate_configuration()`). Together, these three issues describe the full gap between the library's two documented entry points. - `README.md` "Quick start" (`ReactiveCleverAgentsApp` as the primary documented entry point) vs. `docs/guides/reasoning-aware-llm-agents.md` (`create_executor`, documented specifically for non-native-provider/credential-injection scenarios). - `src/cleveractors/core/application.py` lines 68-76 (`ReactiveCleverAgentsApp.__init__` signature — no `credentials` parameter), lines 236-253 (`AgentFactory` construction). - `src/cleveractors/agents/llm_client.py` lines 31-58 (`build_chat_model` docstring — explicit statement that standalone mode rejects non-native providers). - `src/cleveractors/agents/factory.py` (`AgentFactory.__init__`'s existing `credentials` parameter and ADR-2026 per-request credential injection, already used by `create_executor`). ## Subtasks - [ ] Add `credentials` parameter to `ReactiveCleverAgentsApp.__init__` and thread it through `load_configuration()` to `AgentFactory(...)`. - [ ] Confirm `AgentFactory`'s existing per-request credential-injection semantics (ADR-2026: skip caching when credentials are supplied) hold correctly when driven from this constructor path. - [ ] Tests (Behave): non-native-provider credential injection via `ReactiveCleverAgentsApp`. - [ ] Verify coverage >=97% via `nox -s coverage_report`. - [ ] Run `nox` (all default sessions), fix any errors. ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done.
CoreRasurae added this to the v2.1.0 milestone 2026-08-09 22:32:41 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveractors-core#123
No description provided.