Skip to content

Add PerModelCapability for model-specific capability routing#4969

Open
DouweM wants to merge 1 commit intomainfrom
per-model-capability
Open

Add PerModelCapability for model-specific capability routing#4969
DouweM wants to merge 1 commit intomainfrom
per-model-capability

Conversation

@DouweM
Copy link
Copy Markdown
Collaborator

@DouweM DouweM commented Apr 3, 2026

Summary

  • Adds PerModelCapability, a generic capability that routes to different implementations based on the model
  • Accepts a routes dict mapping model class or system string to capability instance
  • Configurable fallback: None (error, default), 'ignore' (no-op), or a capability instance
  • Unwraps WrapperModel, rejects FallbackModel
  • Calls for_run on matched/fallback capabilities
  • Split out from Add server-side compaction support via OpenAICompaction and AnthropicCompaction capabilities #4943 (compaction support) for independent review

Test plan

  • TestPerModelCapability with 8 tests covering routing, fallback, error cases
  • Spec/schema snapshot tests updated

🤖 Generated with Claude Code

A new generic capability that delegates to different implementations
based on the model. Accepts a routes dict mapping model class or
system string to capability instance, with configurable fallback
behavior (error, ignore, or custom capability).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions bot added size: M Medium PR (101-500 weighted lines) feature New feature request, or PR implementing a feature (enhancement) labels Apr 3, 2026
DouweM added a commit that referenced this pull request Apr 3, 2026
Remove PerModelCapability (routed.py, tests, docs) from this branch.
It will be merged independently via #4969, keeping this PR focused
on compaction support only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 4 additional findings in Devin Review.

Open in Devin Review

},
fallback='ignore', # silently skip unsupported models
)
agent = Agent('openai:gpt-4o', capabilities=[cap])
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.

🔴 Doc example uses outdated model gpt-4o instead of frontier model gpt-5.2

Line 776 uses 'openai:gpt-4o' while every other example in the same file (lines 78, 99, 176, 206, 259, 302, 342, 376, 460, 566, 741, 833, 889) uses 'openai:gpt-5.2'. This violates the mandatory rule in agent_docs/index.md (rule:-2): "Use latest frontier models (e.g. openai:gpt-5.2, anthropic:claude-opus-4-6) in docs/examples — Outdated model references make our product look unmaintained and reduce user trust."

Suggested change
agent = Agent('openai:gpt-4o', capabilities=[cap])
agent = Agent('openai:gpt-5.2', capabilities=[cap])
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


The `fallback` parameter controls what happens when no route matches:

- `None` (default) — raise a `UserError`
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.

🔴 UserError not linked with MkDocs reference syntax in docs prose

Line 783 mentions `UserError` as plain backtick text, but per docs/.cursor/rules.mdc ("Always reference the python code in the docs e.g. ModelSettings should link to [ModelSettings][pydantic_ai.settings.ModelSettings]") and docs/AGENTS.md rule:66, all API elements must use reference-style links. The same file already links UserError correctly at docs/capabilities.md:144 as [`UserError`][pydantic_ai.exceptions.UserError].

Suggested change
- `None` (default) — raise a `UserError`
- `None` (default) — raise a [`UserError`][pydantic_ai.exceptions.UserError]
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

Docs Preview

commit: 6819960
Preview URL: https://005c3010-pydantic-ai-previews.pydantic.workers.dev

Comment on lines +770 to +773
routes={
'openai': my_openai_capability,
'anthropic': my_anthropic_capability,
},
Copy link
Copy Markdown

@slmnsh slmnsh Apr 7, 2026

Choose a reason for hiding this comment

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

I think this can be part of existing Capability primitive:

class Capability():
  for: str | None = None
# returns capability that only works with Anthropic
CodeExecutionCapability().for("anthropic")

# OR pass a function that decides whether to use that capability or not
# useful for feature flags / dynamic capability injection
def feature_flag(ctx: RunContext):
  return is_feature_enabled("code-execution")
CodeExecutionCapability().for(feature_flag)

What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature request, or PR implementing a feature (enhancement) size: M Medium PR (101-500 weighted lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants