Skip to content

refactor: reorganize model providers with subpath exports and rename classes#694

Open
pgrayy wants to merge 2 commits intostrands-agents:mainfrom
pgrayy:agent-tasks/model-subpath-exports
Open

refactor: reorganize model providers with subpath exports and rename classes#694
pgrayy wants to merge 2 commits intostrands-agents:mainfrom
pgrayy:agent-tasks/model-subpath-exports

Conversation

@pgrayy
Copy link
Member

@pgrayy pgrayy commented Mar 18, 2026

Motivation

The current model provider class names are generic (BedrockModel, OpenAIModel, etc.) and the import paths sit at the package root (@strands-agents/sdk). As we add more providers and API variants (e.g., OpenAI Responses API alongside Chat Completions), generic names become ambiguous and root-level exports create a cluttered namespace.

This PR does two things:

  1. Moves model providers to dedicated subpath exports (@strands-agents/sdk/models/<provider>), keeping the main entry point focused on core SDK types.
  2. Names each class after the API it wraps, not the provider company, since the subpath already communicates the provider.
Provider API Import Class
AWS Bedrock Converse @strands-agents/sdk/models/bedrock ConverseModel
OpenAI Chat Completions @strands-agents/sdk/models/openai ChatModel
Anthropic Messages @strands-agents/sdk/models/anthropic MessagesModel
Google GenAI @strands-agents/sdk/models/google GenAIModel

This convention scales naturally. Adding OpenAI Responses support later would be ResponsesModel alongside ChatModel under the same ./models/openai subpath with no naming collision.

Why drop the provider prefix?

When a class lives behind a module path like /models/bedrock, repeating "Bedrock" in the class name is redundant. The import path already tells you the provider; the class name should tell you the API.

Node.js core modules follow this pattern. The subpath provides the scoping context, and the exports just describe what they do:

  • node:fs/promises exports readFile, writeFile, mkdir, not fsReadFile or fsPromisesWriteFile. The module path carries the context.
  • node:stream/web exports ReadableStream, WritableStream, TransformStream, not StreamReadableStream or WebReadableStream.
  • node:stream/consumers exports text(), json(), buffer(), not streamConsumersText or streamJson.
  • node:path/posix and node:path/win32 both export join, resolve, basename, not posixJoin or win32Resolve. The subpath tells you the platform variant, the function name tells you the operation.

That last one is a close analogy to what we are doing here. path/posix and path/win32 are two implementations of the same interface, scoped by subpath. Similarly, models/bedrock and models/openai are two implementations of Model, scoped by subpath.

The same short names are used everywhere, including the top-level re-export of the default Bedrock provider. There is no ambiguity at the top level because each provider's API name is already distinct (ConverseModel, ChatModel, MessagesModel, GenAIModel). Users who want a longer form for clarity can alias on import:

import { ConverseModel as BedrockConverseModel } from '@strands-agents/sdk'

Or use namespace imports:

import * as bedrock from '@strands-agents/sdk/models/bedrock'
const model = new bedrock.ConverseModel({ region: 'us-east-1' })

Public API Changes

Each provider now has a dedicated subpath export:

import { ConverseModel } from '@strands-agents/sdk/models/bedrock'
import { ChatModel } from '@strands-agents/sdk/models/openai'
import { MessagesModel } from '@strands-agents/sdk/models/anthropic'
import { GenAIModel } from '@strands-agents/sdk/models/google'

The Bedrock provider is also re-exported from the main @strands-agents/sdk entry point since Bedrock is the default provider:

import { Agent, ConverseModel } from '@strands-agents/sdk'

Other providers are only available through their respective subpath exports.

Config and options types follow the same pattern (e.g., ConverseModelConfig, ChatModelOptions). The Gemini directory is renamed to google/ and all Gemini-prefixed SDK types become GenAI-prefixed, while upstream API references (model IDs, env vars) remain as "gemini."

Since the SDK is still in preview, no backward compatibility aliases are provided.

Documentation PR

strands-agents/docs#682

Type of Change

Breaking change

Testing

  • I ran npm run check

All 1632 unit tests pass. Lint, format, and type-check all pass via pre-commit hooks.

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Additional Considerations

This PR updates the naming to reflect how the model providers are implemented today. However, we could iterate on this and implement an aggregated provider that switches between APIs based on the configurations passed in. For example, we could one day expose an OpenAIModel and set it up to support both chat completions and responses based on configs or based on streaming options that are controlled dynamically. Nothing stops us from doing that. But at least with what we have implemented now, changing the name to reflect the implementation I think is beneficial.

@github-actions github-actions bot added the strands-running <strands-managed> Whether or not an agent is currently running label Mar 18, 2026
@github-actions
Copy link

Code Review Summary

Assessment: Approve ✅

Well-structured refactoring that establishes a clear naming convention for model providers (<Provider><API>Model) and organizes them into dedicated subpath exports.

Review Notes

Nice work on the comprehensive rename and the forward-thinking naming convention!

@github-actions github-actions bot removed the strands-running <strands-managed> Whether or not an agent is currently running label Mar 18, 2026
@pgrayy pgrayy temporarily deployed to manual-approval March 18, 2026 21:58 — with GitHub Actions Inactive
@github-actions github-actions bot added the strands-running <strands-managed> Whether or not an agent is currently running label Mar 18, 2026
@github-actions
Copy link

Thanks for addressing the feedback! The unused import has been removed.

All previous review comments have been addressed - this looks good to merge. 🚀

@github-actions github-actions bot removed the strands-running <strands-managed> Whether or not an agent is currently running label Mar 18, 2026
@pgrayy
Copy link
Member Author

pgrayy commented Mar 19, 2026

Note, to shorten the names, a pattern we could promote instead is something like bedrock.ts:ConverseModel followed by:

import {ConverseModel as BedrockConverseModel} from '@strands-agents/sdk/models/bedrock'
...
model = new BedrockConverseModel

or

import {* as bedrock} from '@strands-agents/sdk/models/bedrock'
...
model = new bedrock.ConverseModel(...)

"./gemini": {
"types": "./dist/src/models/gemini/model.d.ts",
"default": "./dist/src/models/gemini/model.js"
"./models/google": {
Copy link
Member

Choose a reason for hiding this comment

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

Do we need the models prefix here? Is it for tree shaking?

Copy link
Member Author

@pgrayy pgrayy Mar 20, 2026

Choose a reason for hiding this comment

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

It's just for namespacing:

import { ChatModel } from '@strands-agents/sdk/models/openai'

vs

import { ChatModel } from '@strands-agents/sdk/openai'

Tree shaking works just the same.

@pgrayy pgrayy force-pushed the agent-tasks/model-subpath-exports branch from 4627722 to c4ef5fe Compare March 20, 2026 22:04
@github-actions github-actions bot added the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@github-actions
Copy link

Code Review Summary

Assessment: Request Changes ⚠️

There's a significant discrepancy between the PR description and the actual implementation that needs to be resolved.

Critical Issue: PR Description vs Implementation Mismatch

The PR description documents one naming convention, but the implementation uses a different one:

PR Description Says Implementation Has
BedrockConverseModel ConverseModel
OpenAIChatModel ChatModel
AnthropicMessagesModel MessagesModel
GoogleGenAIModel GenAIModel

Action needed: Either update the PR description to match the implementation, or update the implementation to match the description. The PR description serves as documentation for future reference.

Naming Convention Considerations

The shorter names (ConverseModel, ChatModel, etc.) have tradeoffs worth considering:

Pros:

  • Shorter, less verbose
  • Works well with namespace imports: import * as bedrock from '...'; bedrock.ConverseModel
  • Users can alias if they want the longer form: import { ConverseModel as BedrockConverseModel }

Cons:

  • Less self-documenting in isolation (what provider is ChatModel? MessagesModel?)
  • ConverseModel and MessagesModel don't clearly indicate the provider
  • Code reading requires knowing the import path for context

The original <Provider><API>Model convention in the PR description was more explicit. Worth a team discussion on which approach is preferred.

Once the PR description is updated to reflect the actual implementation (or vice versa), this will be ready for final review.

@github-actions github-actions bot removed the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@github-actions github-actions bot added the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026

```typescript
import { Agent, BedrockModel } from '@strands-agents/sdk'
import { Agent, ConverseModel } from '@strands-agents/sdk'

Choose a reason for hiding this comment

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

Issue: Import name doesn't match export

The main entry point exports BedrockConverseModel (aliased from ConverseModel), but this code uses ConverseModel which won't be found.

Suggestion: Update to use the exported name:

import { Agent, BedrockConverseModel } from '@strands-agents/sdk'

const model = new BedrockConverseModel({
  // ...
})

This also applies to lines 246 and 273 in the Graph and Swarm examples.

@github-actions
Copy link

Code Review Summary (Updated)

Assessment: Request Changes ⚠️

The PR description has been updated and now clearly explains the naming convention. However, there's an inconsistency in the README that needs to be fixed.

Issue: README.md uses wrong import name

The main entry point exports BedrockConverseModel, but README.md uses ConverseModel:

// README.md (current - incorrect)
import { Agent, ConverseModel } from '@strands-agents/sdk'

// Should be
import { Agent, BedrockConverseModel } from '@strands-agents/sdk'

This affects lines 101, 246, and 273 in README.md.

What's Good
  • ✅ PR description now explains the naming rationale well (Node.js core modules pattern)
  • ✅ Examples in examples/ directory use correct BedrockConverseModel import
  • ✅ Vended tools README files use correct imports
  • needs-api-review label is present
  • ✅ Documentation PR linked

Once the README.md imports are fixed to use BedrockConverseModel, this is ready to approve.

@github-actions github-actions bot removed the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
pgrayy added 2 commits March 20, 2026 18:46
…classes

- Rename BedrockModel to BedrockConverseModel
- Rename OpenAIModel to OpenAIChatModel
- Rename AnthropicModel to AnthropicMessagesModel
- Rename GeminiModel to GoogleGenAIModel
- Move src/models/gemini/ to src/models/google/
- Add subpath exports: ./models/bedrock, ./models/openai, ./models/anthropic, ./models/google
- Rename all config/options types to match class names
- Update all tests, examples, docs, and READMEs
Rename model providers to shorter, API-focused names:
- BedrockConverseModel -> ConverseModel
- OpenAIChatModel -> ChatModel
- AnthropicMessagesModel -> MessagesModel
- GoogleGenAIModel -> GenAIModel

All related types (Config, Options, etc.) renamed accordingly.
Updated all source, tests, examples, and documentation.
@pgrayy pgrayy force-pushed the agent-tasks/model-subpath-exports branch from 5785500 to 3dafc1e Compare March 20, 2026 22:48
@pgrayy pgrayy temporarily deployed to manual-approval March 20, 2026 22:48 — with GitHub Actions Inactive
@github-actions github-actions bot added the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@github-actions
Copy link

Code Review Summary (Follow-up)

Assessment: Request Changes ⚠️

The README.md import issue from the previous review is still outstanding.

Blocking Issue: README.md uses ConverseModel but the main entry point only exports BedrockConverseModel:

// src/index.ts exports:
export { ConverseModel as BedrockConverseModel } from './models/bedrock.js'

// README.md incorrectly uses:
import { Agent, ConverseModel } from '@strands-agents/sdk'  // ❌ Won't work

Lines to fix in README.md:

  • Line 101, 103: Change ConverseModelBedrockConverseModel
  • Line 246, 248: Change ConverseModelBedrockConverseModel
  • Line 273, 275: Change ConverseModelBedrockConverseModel

Once this is fixed, the PR is ready to approve. Everything else looks good!

@github-actions github-actions bot removed the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@github-actions github-actions bot added the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@github-actions
Copy link

Code Review Summary

Assessment: Approve ✅

The README.md import issue has been fixed. All imports now correctly use BedrockConverseModel from the main entry point.

Review Summary
  • ✅ README.md now uses correct BedrockConverseModel imports
  • ✅ PR description clearly explains the naming convention (Node.js core modules pattern)
  • ✅ Examples in examples/ directory use correct imports
  • ✅ Vended tools documentation uses correct imports
  • needs-api-review label present
  • ✅ Documentation PR linked

Note: There's still an open question from @Unshure about the models prefix in the subpath (package.json:25) that may warrant a response, but it's not blocking.

Nice work on this well-documented refactor!

@github-actions github-actions bot removed the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@pgrayy pgrayy force-pushed the agent-tasks/model-subpath-exports branch from 71e7ff1 to 3b9b3c4 Compare March 20, 2026 23:10
@pgrayy pgrayy deployed to manual-approval March 20, 2026 23:10 — with GitHub Actions Active
@github-actions github-actions bot added the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@github-actions github-actions bot removed the strands-running <strands-managed> Whether or not an agent is currently running label Mar 20, 2026
@strands-agents strands-agents deleted a comment from github-actions bot Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants