DEV Community

Solon Framework
Solon Framework

Posted on

Solon AI 4.0.5: Propagate HTTP Customization from Harness Engine to Every AI Call

If you run a multi-agent workload with Solon AI Harness, you've probably hit this: each agent talks to a model provider over HTTP, and you want all of those requests to carry the same User-Agent, go through the same proxy, or share a custom header. Before 4.0.5 you had to configure each agent individually — and if a new agent joined the team, you had to remember to configure it too.

Solon AI 4.0.5 (released 2026-08-11) closes that gap with a small but very useful feature: HTTP customization now propagates from the harness engine down to every model request, through the chain HarnessEngine → ReActAgent → ChatRequest.

The three layers

The feature is built on ModelOptionsAmend (the options base class in solon-ai-core, present since 3.8.4). It carries a Consumer<HttpUtils> hook that is applied right before the HTTP call to the model provider:

protected Consumer<HttpUtils> httpCustomize;
Enter fullscreen mode Exit fullscreen mode

Three methods are involved:

  • httpCustomizeAdd(...) — append a hook; multiple hooks are chained with andThen
  • httpCustomizeSet(...) — replace the hook
  • httpCustomize() — read it back

The propagation happens because putAll() copies httpCustomize along with the rest of the options, and the agent internals forward it at each layer.

Engine-level: configure once, reach everywhere

At the top of the chain, HarnessEngine exposes the hook directly:

HarnessEngine engine = HarnessEngine.of()
        .httpCustomizeAdd(http -> {
            http.userAgent("my-company-ai/1.0");
            http.timeout(60);
        })
        .build();
Enter fullscreen mode Exit fullscreen mode

or, if you build the engine imperatively:

engine.addHttpCustomize(http -> http.proxy("127.0.0.1", 7890));
engine.setHttpCustomize(...); // replaces, doesn't append
Enter fullscreen mode Exit fullscreen mode

Internally these delegate to HarnessOptions — an engine-level "generic HTTP hook", as the source comment puts it. There is also a per-agent override point at ChatOptions, which extends ModelOptionsAmend, so a specific agent can still fine-tune its own hook:

ChatOptions options = new ChatOptions()
        .httpCustomizeAdd(http -> http.header("X-Tenant", "acme"));
Enter fullscreen mode Exit fullscreen mode

The engine hook and the agent hook are combined — not replaced — so both apply to that agent's requests.

What actually gets applied

When AgentFactory builds a sub-agent, it injects the engine-level settings into the agent's model options:

builder.modelOptions(o -> {
    if (engine.getCacheControl() != null) {
        o.cacheControl(engine.getCacheControl());
    }

    o.httpCustomizeAdd(http -> {
        if (Assert.isNotEmpty(engine.getUserAgent())) {
            http.userAgent(engine.getUserAgent());
        }

        if (engine.getHttpProxy() != null) {
            http.proxy(engine.getHttpProxy());
        }

        if (engine.getHttpCustomize() != null) {
            engine.getHttpCustomize().accept(http);
        }
    });
});
Enter fullscreen mode Exit fullscreen mode

Then, inside the agent runtime, the hook travels again: ReasonTask (the ReAct reasoning path) forwards the model options hook, SimpleAgent forwards its own, and finally ChatRequestDescDefault applies it at the moment of the HTTP call:

if (req.getOptions().httpCustomize() != null) {
    req.getOptions().httpCustomize().accept(httpUtils);
}
Enter fullscreen mode Exit fullscreen mode

That last line is where the hook finally touches the wire — once, for every request, from every agent in the harness.

A naming cleanup worth knowing

4.0.5 also deprecated one method: ChatOptions.httpCustomize(Consumer) is now marked @deprecated in favor of httpCustomizeAdd(...). The old name implied a setter but actually appended; the new name says what it does. Migration is a one-word rename.

A nice synergy with Solon 4.0.5

This lands in the same release cycle as Solon 4.0.5, which gave solon-net-httputils a default User-Agent (solon-http/<version>) and a global HttpConfiguration.setUserAgent(...) override. Between the two, HTTP-level hygiene for model calls is covered end to end: the framework's default UA for generic HTTP, and the AI layer's per-engine hook for model requests — both overridable in one place.

Also in 4.0.5

Beyond the headline feature, this release is mostly polish and fixes:

  • solon-ai-mcp — tolerate SSE messages without an event type
  • solon-ai-dialect-openai — better openai-responses dialect adaptation
  • solon-ai-harnessTaskTalent gains a maxTasks limit
  • solon-ai-talent-webCodeSearchTalent and WebsearchTalent adaptations
  • solon-ai-talent-memory — improved prompts and search capability
  • solon-ai-talent-cli — better TerminalTalent prompts; fixed a Windows environment-variable mis-detection issue
  • solon-ai-talent-mountMountManager adds disallowSkills
  • solon-ai-talent-gateway — fixed a potential infinite-recursion in OpenApiV2Resolver

Summary

If you run Solon AI Harness with multiple agents and ever wished the model requests could share one HTTP configuration, 4.0.5 is your release. Configure once at the engine, and the hook rides down through the ReAct agents to every ChatRequest — with per-agent composition when you need it.

Docs: https://solon.noear.org (Solon AI section) · Repo: https://github.com/opensolon/solon-ai

Top comments (0)