feat: config-first construction API (Agent::from_config)#59
Merged
Conversation
Introduces the 0.10 construction API from the roadmap (Design 2), additively — the pre-0.10 builder (Agent::new + with_model/with_model_config) still works unchanged, so nothing is deprecated yet and no existing call site breaks. New constructors: - Agent::from_config(ModelConfig) — selects the built-in provider from config.api, sets the model id from config.id, and resolves the API key from the provider-conventional env var. Kills the provider↔config pairing footgun and the doubly-specified model id. - Agent::from_provider(provider, ModelConfig) — explicit provider (custom impls and test doubles); pair with ModelConfig::mock(). - Agent::from_config_with(®istry, ModelConfig) -> Result<_, AgentBuildError> — resolve against a custom ProviderRegistry. - Agent::set_model(ModelConfig) — switch model mid-session (re-selects provider and re-resolves the env key; explicit keys preserved). - SubAgentTool::from_config / from_provider mirror the above. Supporting changes: - ProviderRegistry stores Arc<dyn StreamProvider> instead of Box, and gains resolve() -> Option<Arc<...>> so a resolved provider can be owned by an Agent without borrowing the registry. - ModelConfig::mock() — a zero-cost, provider="mock" config for tests. - AgentBuildError (exported) for the fallible from_config_with path. Docs & examples migrated to from_config: lib.rs quick-start, README, the mdBook quick-start page, CLAUDE.md (new Construction API section), and all examples. cli.rs is the headline demo — its 12 Agent::new(X).with_model_config sites and the per-provider env-key ceremony collapse into one from_config call each. The remaining mdBook provider/concept pages keep the still-valid old API and will move in the deprecation follow-up. Tests: default-registry protocol coverage + empty-registry miss; from_config wiring/env-key resolution; from_config_with error; from_provider end-to-end; set_model switch; ModelConfig::mock; SubAgentTool::from_provider. Refs the Phase B roadmap; deprecation of the old constructors + full doc sweep + 0.10.0 release land in a focused follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Multi-agent review of the config-first construction API surfaced no shipping bugs but a cluster of real improvements, several flagged independently by multiple reviewers. - set_model no longer silently clobbers a custom provider (flagged by 4 reviewers, the one code change reviewers agreed on). Agent now tracks provider provenance (provider_is_explicit): providers supplied via new / from_provider are KEPT across a model switch (with a warning if they may not serve the new protocol); only registry-resolved providers (from_config) are re-selected. The previously-dead "unregistered protocol" branch now warns instead of silently keeping a mismatched provider. - ModelConfig::mock() doc hardened to a strong "do NOT use with from_config" warning — from_config(mock()) would build the real Anthropic provider pointed at a non-routable base_url and fail at first prompt. - AgentBuildError now derives thiserror::Error (drops the hand-rolled Display/Error impls) to match ProviderError / McpError conventions. - Compile-forced protocol exhaustiveness: the registry coverage test now drives off a wildcard-free match over ApiProtocol, so adding a variant fails to build until it's registered — the invariant behind from_config's unwrap can't silently rot. Added a dispatch-correctness test asserting each protocol resolves to a provider that actually speaks it. - New StreamProvider::protocol() -> Option<ApiProtocol> (default None, overridden by the 7 built-in providers) enables the dispatch test and future mismatch diagnostics. - SubAgentTool::from_config_with added for fallible parity with Agent::from_config_with (previously the sub-agent from_config had only the panic path). - Doc fixes: from_config # Panics now states "never panics" unconditionally (every ApiProtocol is covered); set_model doc states the guaranteed provider handling; registry get() cross-references resolve(); CLAUDE.md "Construction API (0.10+)" heading softened (this PR doesn't bump the version) and notes the SubAgentTool mirrors. Tests: set_model preserves an explicit provider + key across a switch; SubAgentTool::from_config wiring and from_config_with empty-registry error; per-protocol dispatch correctness; exhaustiveness anchor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
yuanhao
added a commit
that referenced
this pull request
Jul 6, 2026
…60) * release: 0.10.0 — deprecate old constructors, migrate to from_config Completes Phase B: the config-first construction API (shipped additively in #59) becomes the recommended path, the old builders are deprecated, and every call site across the codebase and docs migrates to it. Deprecated (since 0.10.0, removed in 1.0 — all still work, with a compiler warning pointing at the replacement): - Agent::new, Agent::with_model, Agent::with_model_config - SubAgentTool::new, SubAgentTool::with_model, SubAgentTool::with_model_config The SubAgentTool from_* builders now route through a private `build()` so they don't trip their own deprecation lint. Migrated to the new API (CI is -Dwarnings, so every compiled call site had to move in this commit): - All examples (code_review, rlm, shared_state; basic/sub_agent/callbacks/ persistence/cli were done in #59) and both src doctests. - All tests, except two kept on the deprecated API under #[allow(deprecated)] to preserve its coverage until 1.0: test_agent_builder_pattern (asserts the builder's effect) and session_cost_usd_none_without_model_config (the no-config None branch is only reachable via Agent::new). - All 19 mdBook pages (providers/concepts/guides/reference). Azure/Bedrock/ Vertex use ModelConfig::custom since no preset exists. Release: - Version 0.10.0. - CHANGELOG.md with a migration guide (before/after table). - README install snippet 0.9 -> 0.10; docs/installation 0.5 -> 0.10 and MSRV 1.56 -> 1.86; README OpenAI-compat example now builds an agent via from_config instead of dangling a registry. Verified: cargo clippy --all-targets --all-features (-Dwarnings) clean; cargo test --all-features all green; cargo doc (-Dwarnings) clean; doctests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: fix PR #60 review findings Doc-accuracy review of the migrated (un-CI-compiled) mdBook pages surfaced: - docs/providers/model-presets.md: `with_thinking_level` is not a real method (it's `with_thinking`) — fixed both occurrences. The migration rewrote these blocks and should have caught the invented call. - docs/getting-started/installation.md: the openapi-feature snippet still pinned `version = "0.5"` (the main install line was bumped to 0.10 but this one was missed) → 0.10; and listed `serde_yaml` where the crate now uses `serde_yaml_ng`. - docs/concepts/prompt-caching.md: the Bedrock row claimed "Automatic (where supported)", contradicting README's "Bedrock has no automatic caching" — reconciled to no automatic caching. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Phase B of the roadmap, landed additively — the pre-0.10 builder (
Agent::new+with_model/with_model_config) still works unchanged. Nothing is deprecated yet, so no existing call site breaks and there's no forced ~240-site sweep in this PR.The win
Before — provider and config must be paired correctly by hand, and the model id is passed twice:
After — provider inferred from
config.api, key fromZAI_API_KEY:New API
Agent::from_config(ModelConfig)— provider fromconfig.api, model id fromconfig.id, key from the provider-conventional env var.Agent::from_provider(provider, ModelConfig)— explicit provider (custom impls, test doubles); pair withModelConfig::mock().Agent::from_config_with(®istry, ModelConfig) -> Result<_, AgentBuildError>— custom registry.Agent::set_model(ModelConfig)— mid-session model switch (re-resolves provider + env key; explicit keys preserved).SubAgentTool::from_config/from_providermirror these.Supporting:
ProviderRegistrynow storesArc<dyn StreamProvider>+ aresolve()accessor;ModelConfig::mock(); exportedAgentBuildError.Docs migrated
lib.rs quick-start, README, mdBook quick-start, CLAUDE.md (new Construction API section), and all examples.
cli.rsis the headline demo: 12Agent::new(X).with_model_config(...)sites + the per-provider env-key ceremony collapse into onefrom_configeach. Remaining mdBook provider/concept pages keep the still-valid old API and move in the deprecation follow-up.Verification
cargo clippy --all-targets --all-features— 0 warnings under-DwarningsRUSTDOCFLAGS=-Dwarnings cargo doc --all-featurescleanNot in this PR (follow-up before 0.10.0)
#[deprecated(since = "0.10.0")]onAgent::new/with_model/with_model_config(+ SubAgentTool mirrors), the full ~240-site + remaining-mdBook sweep, and the 0.10.0 release with a migration guide.🤖 Generated with Claude Code