Skip to content

feat: support provider-level compaction_model default - #3785

Merged
dgageot merged 2 commits into
docker:mainfrom
dgageot:provider-level-compaction-model
Jul 22, 2026
Merged

feat: support provider-level compaction_model default#3785
dgageot merged 2 commits into
docker:mainfrom
dgageot:provider-level-compaction-model

Conversation

@dgageot

@dgageot dgageot commented Jul 22, 2026

Copy link
Copy Markdown
Member

When multiple agents share the same provider, each one previously had to repeat its compaction_model — there was no way to express a default at the provider level. This change adds a compaction_model field to provider definitions so the default can live in one place.

Resolution now follows a clear priority: an agent-level compaction_model wins, then a model-level one, then the provider-level default. Note that this intentionally flips the previous precedence where model-level beat agent-level. The logic is centralized in config.EffectiveCompactionModelRef (pkg/config/compaction.go), which is now the single source of truth consumed by the team loader, first_available reachability checks, and the credential preflight.

Two other gaps are closed at the same time: first_available selectors that are only referenced through a compaction_model (at any level) are now resolved at load time, and the credential preflight includes the effective compaction model's env vars so a missing API key surfaces in the consolidated preflight error rather than silently at runtime.

agent-schema.json, examples/compaction_model.yaml, and the docs for agents, models, the compaction guide, and custom providers are all updated to reflect the new field.

dgageot added 2 commits July 22, 2026 11:11
Resolution priority is now agent > model > provider, which also flips the
previous model-over-agent precedence.

Assisted-By: Claude
…d env preflight

Extract precedence logic into config.EffectiveCompactionModelRef; wire it into
first_available reachability and credential preflight so a compaction model
named only at the provider level is never silently skipped.

Assisted-By: Claude
@dgageot
dgageot requested a review from a team as a code owner July 22, 2026 09:31
@aheritier aheritier added area/config For configuration parsing, YAML, environment variables area/docs Documentation changes kind/feat PR adds a new feature (maps to feat:). Use on PRs only. labels Jul 22, 2026

@docker-agent docker-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟡 NEEDS ATTENTION

This PR centralizes compaction-model resolution into EffectiveCompactionModelRef and the new priority order (agent > model > provider) is correctly implemented and documented. One gap was found in the new provider-level lookup path.

Comment thread pkg/config/compaction.go
Comment on lines +29 to +38
for name := range strings.SplitSeq(a.Model, ",") {
modelCfg, ok := cfg.Models[name]
if !ok {
continue
}
if providerCfg, ok := cfg.Providers[modelCfg.Provider]; ok && providerCfg.CompactionModel != "" {
return providerCfg.CompactionModel
}
}
return ""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] Provider-level compaction_model is never applied when agent.Model is an inline provider/model spec

The second loop in EffectiveCompactionModelRef tries to resolve the provider-level default by looking up each model name in cfg.Models and then finding its .Provider. When agent.Model is an inline spec such as "openai/gpt-4o" (not a named entry in cfg.Models), the !ok guard causes the loop to continue, so cfg.Providers["openai"].CompactionModel is never consulted.

The provider can be extracted from inline specs with the already-available latest.ParseModelRef, which is exactly what gatherEnvVarsForCompactionModel does for the compaction ref itself (gather.go). Applying the same pattern here closes the gap:

Suggested change
for name := range strings.SplitSeq(a.Model, ",") {
modelCfg, ok := cfg.Models[name]
if !ok {
continue
}
if providerCfg, ok := cfg.Providers[modelCfg.Provider]; ok && providerCfg.CompactionModel != "" {
return providerCfg.CompactionModel
}
}
return ""
for name := range strings.SplitSeq(a.Model, ",") {
var provider string
if modelCfg, ok := cfg.Models[name]; ok {
provider = modelCfg.Provider
} else if parsed, err := latest.ParseModelRef(strings.TrimSpace(name)); err == nil {
provider = parsed.Provider
}
if provider != "" {
if providerCfg, ok := cfg.Providers[provider]; ok && providerCfg.CompactionModel != "" {
return providerCfg.CompactionModel
}
}
}
return ""

Without this fix, a user who sets compaction_model at the provider level and uses an inline model reference (e.g. model: openai/gpt-4o) will silently get no compaction model, contrary to what the ProviderConfig.CompactionModel doc comment promises ("agents whose model uses this provider").

Confidence Score
🟡 moderate 67/100

@dgageot
dgageot merged commit 33735ae into docker:main Jul 22, 2026
17 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config For configuration parsing, YAML, environment variables area/docs Documentation changes kind/feat PR adds a new feature (maps to feat:). Use on PRs only.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants