pyagent-providers 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ *.egg
9
+ .venv/
10
+ venv/
11
+ .mypy_cache/
12
+ .ruff_cache/
13
+ .pytest_cache/
14
+ .coverage
15
+ htmlcov/
16
+ site/
17
+ .env
18
+ *.log
@@ -0,0 +1,347 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyagent-providers
3
+ Version: 0.1.0
4
+ Summary: Multi-provider abstraction with capability negotiation, health checks, and fallback chains
5
+ Project-URL: Homepage, https://pyagent.org
6
+ Project-URL: Repository, https://github.com/pyagent-core/pyagent
7
+ Project-URL: Documentation, https://pyagent.org
8
+ Author-email: PyAgent Team <team@pyagent.org>
9
+ License: MIT
10
+ Keywords: LLM,agents,fallback,multi-provider,providers,routing
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: pyagent-patterns>=0.1.0
21
+ Requires-Dist: pyagent-router>=0.1.0
22
+ Provides-Extra: all
23
+ Requires-Dist: anthropic>=0.30; extra == 'all'
24
+ Requires-Dist: litellm>=1.40; extra == 'all'
25
+ Requires-Dist: openai>=1.30; extra == 'all'
26
+ Provides-Extra: anthropic
27
+ Requires-Dist: anthropic>=0.30; extra == 'anthropic'
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.10; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: ruff>=0.5; extra == 'dev'
33
+ Provides-Extra: litellm
34
+ Requires-Dist: litellm>=1.40; extra == 'litellm'
35
+ Provides-Extra: openai
36
+ Requires-Dist: openai>=1.30; extra == 'openai'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # pyagent-providers
40
+
41
+ **Multi-provider abstraction with capability negotiation, health checks, fallback chains, and cost-optimized routing** for multi-agent LLM systems. Drop-in replacement for hardcoded model specs.
42
+
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE)
44
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
45
+
46
+ ## Install
47
+
48
+ ```bash
49
+ pip install pyagent-providers # Core (includes MockProvider)
50
+ pip install pyagent-providers[openai] # + OpenAI adapter
51
+ pip install pyagent-providers[anthropic] # + Anthropic adapter
52
+ pip install pyagent-providers[litellm] # + LiteLLM (100+ models)
53
+ pip install pyagent-providers[all] # All adapters
54
+ ```
55
+
56
+ Depends on: `pyagent-patterns`, `pyagent-router`.
57
+
58
+ ## Why Provider Abstraction?
59
+
60
+ Without `pyagent-providers`, switching models means rewriting LLM wrappers. With it, your agents talk to a `ProviderProtocol` that satisfies the existing `LLMCallable` interface — so every provider is a drop-in replacement for `Agent.llm`.
61
+
62
+ ```python
63
+ from pyagent_patterns.base import Agent
64
+ from pyagent_providers.adapters.mock import MockProvider
65
+
66
+ # Any provider works as an Agent's LLM
67
+ provider = MockProvider(name="test", responses=["Hello"])
68
+ agent = Agent("greeter", provider) # provider satisfies LLMCallable
69
+ ```
70
+
71
+ ## ProviderProtocol — The Interface
72
+
73
+ Every provider implements this:
74
+
75
+ ```python
76
+ from pyagent_providers import ProviderProtocol, HealthStatus, ProviderCapabilities
77
+
78
+ class MyCustomProvider:
79
+ @property
80
+ def name(self) -> str:
81
+ return "my_provider"
82
+
83
+ @property
84
+ def capabilities(self) -> ProviderCapabilities:
85
+ return ProviderCapabilities(
86
+ models=["my-model-small", "my-model-large"],
87
+ capabilities={Capability.GENERAL, Capability.CODE},
88
+ max_context=128_000,
89
+ supports_streaming=True,
90
+ )
91
+
92
+ async def health(self) -> HealthStatus:
93
+ # check your endpoint
94
+ return HealthStatus.HEALTHY
95
+
96
+ async def complete(self, messages, model=None) -> str:
97
+ # call your API
98
+ return "response"
99
+
100
+ async def __call__(self, messages) -> str:
101
+ return await self.complete(messages)
102
+ ```
103
+
104
+ ## ProviderRegistry — Register and Discover
105
+
106
+ ```python
107
+ import asyncio
108
+ from pyagent_providers import ProviderRegistry, HealthStatus
109
+ from pyagent_providers.adapters.mock import MockProvider
110
+ from pyagent_router.selector import Capability
111
+
112
+ registry = ProviderRegistry()
113
+
114
+ async def setup():
115
+ await registry.register(MockProvider(
116
+ name="openai",
117
+ models=["gpt-4o-mini", "gpt-4o"],
118
+ capabilities={Capability.GENERAL, Capability.CODE, Capability.VISION},
119
+ ))
120
+ await registry.register(MockProvider(
121
+ name="anthropic",
122
+ models=["claude-haiku-3.5", "claude-sonnet-4"],
123
+ capabilities={Capability.GENERAL, Capability.CODE, Capability.CREATIVE},
124
+ ))
125
+
126
+ # Discover by capability
127
+ coders = registry.discover({Capability.CODE})
128
+ print([p.name for p in coders]) # ["openai", "anthropic"]
129
+
130
+ vision = registry.discover({Capability.VISION})
131
+ print([p.name for p in vision]) # ["openai"]
132
+
133
+ # Health check all
134
+ statuses = await registry.check_health()
135
+ print(statuses) # {"openai": "healthy", "anthropic": "healthy"}
136
+
137
+ # Remove unhealthy
138
+ removed = await registry.remove_unhealthy()
139
+ print(f"Removed: {removed}") # []
140
+
141
+ asyncio.run(setup())
142
+ ```
143
+
144
+ ## ProviderRouter — Strategy-Based Routing
145
+
146
+ Four strategies: `CAPABILITY_FIRST`, `COST_FIRST`, `LATENCY_FIRST`, `ROUND_ROBIN`.
147
+
148
+ ```python
149
+ from pyagent_providers import ProviderRouter, RoutingStrategy
150
+ from pyagent_patterns.base import Message
151
+
152
+ # Capability-first (default): pick the provider with broadest capabilities
153
+ router = ProviderRouter(registry, strategy=RoutingStrategy.CAPABILITY_FIRST)
154
+ provider, model = asyncio.run(router.route(
155
+ [Message.user("Write a Python REST API with FastAPI")],
156
+ required={Capability.CODE},
157
+ ))
158
+ print(f"{provider.name}/{model}")
159
+
160
+ # Cost-first: cheapest provider + model for the task
161
+ router = ProviderRouter(registry, strategy=RoutingStrategy.COST_FIRST)
162
+ provider, model = asyncio.run(router.route([Message.user("What is 2+2?")]))
163
+ print(f"{provider.name}/{model}") # picks gpt-4.1-nano
164
+
165
+ # Round-robin: cycle through providers for load distribution
166
+ router = ProviderRouter(registry, strategy=RoutingStrategy.ROUND_ROBIN)
167
+ for _ in range(4):
168
+ provider, model = asyncio.run(router.route([Message.user("Balance me")]))
169
+ print(provider.name, end=" ")
170
+ # openai anthropic openai anthropic
171
+ ```
172
+
173
+ ## FallbackChain — Resilient Completion
174
+
175
+ Try providers in order. If one fails, fall through to the next. Optionally integrates with `CircuitBreaker` from `pyagent-patterns`.
176
+
177
+ ```python
178
+ from pyagent_providers import FallbackChain
179
+
180
+ chain = FallbackChain(providers=[
181
+ primary_openai, # try first
182
+ fallback_anthropic, # if OpenAI fails
183
+ emergency_litellm, # last resort
184
+ ])
185
+
186
+ result = asyncio.run(chain.complete([Message.user("Important task")]))
187
+ print(result.output) # response from first successful provider
188
+ print(result.provider_name) # which provider answered
189
+ print(result.attempts) # full attempt log with errors
190
+
191
+ # With circuit breaker integration
192
+ from pyagent_patterns.recovery import CircuitBreaker
193
+
194
+ chain = FallbackChain(
195
+ providers=[primary, fallback],
196
+ circuit_breakers={
197
+ "primary": CircuitBreaker(failure_threshold=3, reset_timeout_seconds=60),
198
+ },
199
+ )
200
+ ```
201
+
202
+ ## CapabilityNegotiator — Match Task Requirements
203
+
204
+ Scores providers by capability overlap, context window, and feature support.
205
+
206
+ ```python
207
+ from pyagent_providers import CapabilityNegotiator
208
+
209
+ negotiator = CapabilityNegotiator(registry)
210
+
211
+ # Find best provider for code + reasoning tasks
212
+ result = negotiator.negotiate(
213
+ required_capabilities={Capability.CODE, Capability.REASONING},
214
+ min_context=100_000,
215
+ )
216
+ if result:
217
+ print(result.provider.name) # "openai" or "anthropic"
218
+ print(result.model) # best model from that provider
219
+ print(f"Match: {result.match_score:.0%}")
220
+ print(result.matched_capabilities) # {CODE, REASONING}
221
+ print(result.missing_capabilities) # set()
222
+
223
+ # Get all ranked matches
224
+ all_matches = negotiator.negotiate_all(
225
+ required_capabilities={Capability.GENERAL},
226
+ limit=5,
227
+ )
228
+ for m in all_matches:
229
+ print(f" {m.provider.name}: {m.match_score:.0%}")
230
+ ```
231
+
232
+ ## CostOptimizer — Multi-Provider Cost Comparison
233
+
234
+ ```python
235
+ from pyagent_providers import CostOptimizer
236
+
237
+ optimizer = CostOptimizer(registry)
238
+
239
+ # Compare all providers for a task
240
+ estimates = optimizer.compare("Explain distributed consensus algorithms")
241
+ for est in estimates[:5]:
242
+ print(f"{est.provider_name}/{est.model}: ${est.estimate.total_cost:.7f}")
243
+
244
+ # Get cheapest option
245
+ cheapest = optimizer.cheapest("Simple greeting task")
246
+ if cheapest:
247
+ print(f"Use {cheapest.provider_name}/{cheapest.model}: ${cheapest.estimate.total_cost:.7f}")
248
+
249
+ # Get provider object + model for direct use
250
+ pair = optimizer.cheapest_provider("My task")
251
+ if pair:
252
+ provider, model = pair
253
+ agent = Agent("my_agent", provider)
254
+ ```
255
+
256
+ ## Adapter Examples
257
+
258
+ ### OpenAI
259
+
260
+ ```python
261
+ from pyagent_providers.adapters.openai import OpenAIProvider
262
+
263
+ openai = OpenAIProvider(
264
+ api_key="sk-...", # or set OPENAI_API_KEY env var
265
+ default_model="gpt-4o-mini",
266
+ models=["gpt-4o-mini", "gpt-4o", "o3-mini"],
267
+ )
268
+
269
+ await registry.register(openai)
270
+ result = await openai.complete([Message.user("Hello")])
271
+ ```
272
+
273
+ ### Anthropic
274
+
275
+ ```python
276
+ from pyagent_providers.adapters.anthropic import AnthropicProvider
277
+
278
+ anthropic = AnthropicProvider(
279
+ api_key="sk-ant-...",
280
+ default_model="claude-sonnet-4-20250514",
281
+ )
282
+
283
+ await registry.register(anthropic)
284
+ result = await anthropic.complete([Message.user("Hello")])
285
+ ```
286
+
287
+ ### LiteLLM (100+ Providers)
288
+
289
+ ```python
290
+ from pyagent_providers.adapters.litellm import LiteLLMProvider
291
+
292
+ litellm = LiteLLMProvider(
293
+ models=["gpt-4o-mini", "anthropic/claude-haiku-3.5", "gemini/gemini-2.5-flash"],
294
+ default_model="gpt-4o-mini",
295
+ )
296
+
297
+ await registry.register(litellm)
298
+ result = await litellm.complete([Message.user("Hello")], model="gemini/gemini-2.5-flash")
299
+ ```
300
+
301
+ ### MockProvider (Testing)
302
+
303
+ ```python
304
+ from pyagent_providers.adapters.mock import MockProvider
305
+
306
+ mock = MockProvider(
307
+ name="test",
308
+ responses=["Response 1", "Response 2"],
309
+ models=["mock-fast", "mock-smart"],
310
+ capabilities={Capability.GENERAL, Capability.CODE},
311
+ health_status=HealthStatus.HEALTHY,
312
+ )
313
+
314
+ await registry.register(mock)
315
+ result = await mock.complete([Message.user("Test")])
316
+ print(mock.call_count) # 1
317
+ ```
318
+
319
+ ## Integration with pyagent-patterns
320
+
321
+ ```python
322
+ from pyagent_patterns.base import Agent
323
+ from pyagent_patterns.orchestration import Pipeline
324
+ from pyagent_providers import ProviderRegistry, CapabilityNegotiator
325
+ from pyagent_providers.adapters.mock import MockProvider
326
+
327
+ # Set up providers
328
+ registry = ProviderRegistry()
329
+ registry.register_sync(MockProvider(name="fast", responses=["Extracted facts"]))
330
+ registry.register_sync(MockProvider(name="smart", responses=["Detailed analysis"]))
331
+
332
+ # Use providers as Agent LLMs
333
+ fast = registry.get("fast")
334
+ smart = registry.get("smart")
335
+
336
+ pipeline = Pipeline(stages=[
337
+ Agent("extractor", fast, system_prompt="Extract key facts."),
338
+ Agent("analyst", smart, system_prompt="Analyse in depth."),
339
+ ])
340
+
341
+ result = asyncio.run(pipeline.run("Process this document"))
342
+ print(result.output)
343
+ ```
344
+
345
+ ## Full Documentation
346
+
347
+ See [pyagent.dev](https://pyagent.dev) for full API reference and integration guides.
@@ -0,0 +1,309 @@
1
+ # pyagent-providers
2
+
3
+ **Multi-provider abstraction with capability negotiation, health checks, fallback chains, and cost-optimized routing** for multi-agent LLM systems. Drop-in replacement for hardcoded model specs.
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE)
6
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ pip install pyagent-providers # Core (includes MockProvider)
12
+ pip install pyagent-providers[openai] # + OpenAI adapter
13
+ pip install pyagent-providers[anthropic] # + Anthropic adapter
14
+ pip install pyagent-providers[litellm] # + LiteLLM (100+ models)
15
+ pip install pyagent-providers[all] # All adapters
16
+ ```
17
+
18
+ Depends on: `pyagent-patterns`, `pyagent-router`.
19
+
20
+ ## Why Provider Abstraction?
21
+
22
+ Without `pyagent-providers`, switching models means rewriting LLM wrappers. With it, your agents talk to a `ProviderProtocol` that satisfies the existing `LLMCallable` interface — so every provider is a drop-in replacement for `Agent.llm`.
23
+
24
+ ```python
25
+ from pyagent_patterns.base import Agent
26
+ from pyagent_providers.adapters.mock import MockProvider
27
+
28
+ # Any provider works as an Agent's LLM
29
+ provider = MockProvider(name="test", responses=["Hello"])
30
+ agent = Agent("greeter", provider) # provider satisfies LLMCallable
31
+ ```
32
+
33
+ ## ProviderProtocol — The Interface
34
+
35
+ Every provider implements this:
36
+
37
+ ```python
38
+ from pyagent_providers import ProviderProtocol, HealthStatus, ProviderCapabilities
39
+
40
+ class MyCustomProvider:
41
+ @property
42
+ def name(self) -> str:
43
+ return "my_provider"
44
+
45
+ @property
46
+ def capabilities(self) -> ProviderCapabilities:
47
+ return ProviderCapabilities(
48
+ models=["my-model-small", "my-model-large"],
49
+ capabilities={Capability.GENERAL, Capability.CODE},
50
+ max_context=128_000,
51
+ supports_streaming=True,
52
+ )
53
+
54
+ async def health(self) -> HealthStatus:
55
+ # check your endpoint
56
+ return HealthStatus.HEALTHY
57
+
58
+ async def complete(self, messages, model=None) -> str:
59
+ # call your API
60
+ return "response"
61
+
62
+ async def __call__(self, messages) -> str:
63
+ return await self.complete(messages)
64
+ ```
65
+
66
+ ## ProviderRegistry — Register and Discover
67
+
68
+ ```python
69
+ import asyncio
70
+ from pyagent_providers import ProviderRegistry, HealthStatus
71
+ from pyagent_providers.adapters.mock import MockProvider
72
+ from pyagent_router.selector import Capability
73
+
74
+ registry = ProviderRegistry()
75
+
76
+ async def setup():
77
+ await registry.register(MockProvider(
78
+ name="openai",
79
+ models=["gpt-4o-mini", "gpt-4o"],
80
+ capabilities={Capability.GENERAL, Capability.CODE, Capability.VISION},
81
+ ))
82
+ await registry.register(MockProvider(
83
+ name="anthropic",
84
+ models=["claude-haiku-3.5", "claude-sonnet-4"],
85
+ capabilities={Capability.GENERAL, Capability.CODE, Capability.CREATIVE},
86
+ ))
87
+
88
+ # Discover by capability
89
+ coders = registry.discover({Capability.CODE})
90
+ print([p.name for p in coders]) # ["openai", "anthropic"]
91
+
92
+ vision = registry.discover({Capability.VISION})
93
+ print([p.name for p in vision]) # ["openai"]
94
+
95
+ # Health check all
96
+ statuses = await registry.check_health()
97
+ print(statuses) # {"openai": "healthy", "anthropic": "healthy"}
98
+
99
+ # Remove unhealthy
100
+ removed = await registry.remove_unhealthy()
101
+ print(f"Removed: {removed}") # []
102
+
103
+ asyncio.run(setup())
104
+ ```
105
+
106
+ ## ProviderRouter — Strategy-Based Routing
107
+
108
+ Four strategies: `CAPABILITY_FIRST`, `COST_FIRST`, `LATENCY_FIRST`, `ROUND_ROBIN`.
109
+
110
+ ```python
111
+ from pyagent_providers import ProviderRouter, RoutingStrategy
112
+ from pyagent_patterns.base import Message
113
+
114
+ # Capability-first (default): pick the provider with broadest capabilities
115
+ router = ProviderRouter(registry, strategy=RoutingStrategy.CAPABILITY_FIRST)
116
+ provider, model = asyncio.run(router.route(
117
+ [Message.user("Write a Python REST API with FastAPI")],
118
+ required={Capability.CODE},
119
+ ))
120
+ print(f"{provider.name}/{model}")
121
+
122
+ # Cost-first: cheapest provider + model for the task
123
+ router = ProviderRouter(registry, strategy=RoutingStrategy.COST_FIRST)
124
+ provider, model = asyncio.run(router.route([Message.user("What is 2+2?")]))
125
+ print(f"{provider.name}/{model}") # picks gpt-4.1-nano
126
+
127
+ # Round-robin: cycle through providers for load distribution
128
+ router = ProviderRouter(registry, strategy=RoutingStrategy.ROUND_ROBIN)
129
+ for _ in range(4):
130
+ provider, model = asyncio.run(router.route([Message.user("Balance me")]))
131
+ print(provider.name, end=" ")
132
+ # openai anthropic openai anthropic
133
+ ```
134
+
135
+ ## FallbackChain — Resilient Completion
136
+
137
+ Try providers in order. If one fails, fall through to the next. Optionally integrates with `CircuitBreaker` from `pyagent-patterns`.
138
+
139
+ ```python
140
+ from pyagent_providers import FallbackChain
141
+
142
+ chain = FallbackChain(providers=[
143
+ primary_openai, # try first
144
+ fallback_anthropic, # if OpenAI fails
145
+ emergency_litellm, # last resort
146
+ ])
147
+
148
+ result = asyncio.run(chain.complete([Message.user("Important task")]))
149
+ print(result.output) # response from first successful provider
150
+ print(result.provider_name) # which provider answered
151
+ print(result.attempts) # full attempt log with errors
152
+
153
+ # With circuit breaker integration
154
+ from pyagent_patterns.recovery import CircuitBreaker
155
+
156
+ chain = FallbackChain(
157
+ providers=[primary, fallback],
158
+ circuit_breakers={
159
+ "primary": CircuitBreaker(failure_threshold=3, reset_timeout_seconds=60),
160
+ },
161
+ )
162
+ ```
163
+
164
+ ## CapabilityNegotiator — Match Task Requirements
165
+
166
+ Scores providers by capability overlap, context window, and feature support.
167
+
168
+ ```python
169
+ from pyagent_providers import CapabilityNegotiator
170
+
171
+ negotiator = CapabilityNegotiator(registry)
172
+
173
+ # Find best provider for code + reasoning tasks
174
+ result = negotiator.negotiate(
175
+ required_capabilities={Capability.CODE, Capability.REASONING},
176
+ min_context=100_000,
177
+ )
178
+ if result:
179
+ print(result.provider.name) # "openai" or "anthropic"
180
+ print(result.model) # best model from that provider
181
+ print(f"Match: {result.match_score:.0%}")
182
+ print(result.matched_capabilities) # {CODE, REASONING}
183
+ print(result.missing_capabilities) # set()
184
+
185
+ # Get all ranked matches
186
+ all_matches = negotiator.negotiate_all(
187
+ required_capabilities={Capability.GENERAL},
188
+ limit=5,
189
+ )
190
+ for m in all_matches:
191
+ print(f" {m.provider.name}: {m.match_score:.0%}")
192
+ ```
193
+
194
+ ## CostOptimizer — Multi-Provider Cost Comparison
195
+
196
+ ```python
197
+ from pyagent_providers import CostOptimizer
198
+
199
+ optimizer = CostOptimizer(registry)
200
+
201
+ # Compare all providers for a task
202
+ estimates = optimizer.compare("Explain distributed consensus algorithms")
203
+ for est in estimates[:5]:
204
+ print(f"{est.provider_name}/{est.model}: ${est.estimate.total_cost:.7f}")
205
+
206
+ # Get cheapest option
207
+ cheapest = optimizer.cheapest("Simple greeting task")
208
+ if cheapest:
209
+ print(f"Use {cheapest.provider_name}/{cheapest.model}: ${cheapest.estimate.total_cost:.7f}")
210
+
211
+ # Get provider object + model for direct use
212
+ pair = optimizer.cheapest_provider("My task")
213
+ if pair:
214
+ provider, model = pair
215
+ agent = Agent("my_agent", provider)
216
+ ```
217
+
218
+ ## Adapter Examples
219
+
220
+ ### OpenAI
221
+
222
+ ```python
223
+ from pyagent_providers.adapters.openai import OpenAIProvider
224
+
225
+ openai = OpenAIProvider(
226
+ api_key="sk-...", # or set OPENAI_API_KEY env var
227
+ default_model="gpt-4o-mini",
228
+ models=["gpt-4o-mini", "gpt-4o", "o3-mini"],
229
+ )
230
+
231
+ await registry.register(openai)
232
+ result = await openai.complete([Message.user("Hello")])
233
+ ```
234
+
235
+ ### Anthropic
236
+
237
+ ```python
238
+ from pyagent_providers.adapters.anthropic import AnthropicProvider
239
+
240
+ anthropic = AnthropicProvider(
241
+ api_key="sk-ant-...",
242
+ default_model="claude-sonnet-4-20250514",
243
+ )
244
+
245
+ await registry.register(anthropic)
246
+ result = await anthropic.complete([Message.user("Hello")])
247
+ ```
248
+
249
+ ### LiteLLM (100+ Providers)
250
+
251
+ ```python
252
+ from pyagent_providers.adapters.litellm import LiteLLMProvider
253
+
254
+ litellm = LiteLLMProvider(
255
+ models=["gpt-4o-mini", "anthropic/claude-haiku-3.5", "gemini/gemini-2.5-flash"],
256
+ default_model="gpt-4o-mini",
257
+ )
258
+
259
+ await registry.register(litellm)
260
+ result = await litellm.complete([Message.user("Hello")], model="gemini/gemini-2.5-flash")
261
+ ```
262
+
263
+ ### MockProvider (Testing)
264
+
265
+ ```python
266
+ from pyagent_providers.adapters.mock import MockProvider
267
+
268
+ mock = MockProvider(
269
+ name="test",
270
+ responses=["Response 1", "Response 2"],
271
+ models=["mock-fast", "mock-smart"],
272
+ capabilities={Capability.GENERAL, Capability.CODE},
273
+ health_status=HealthStatus.HEALTHY,
274
+ )
275
+
276
+ await registry.register(mock)
277
+ result = await mock.complete([Message.user("Test")])
278
+ print(mock.call_count) # 1
279
+ ```
280
+
281
+ ## Integration with pyagent-patterns
282
+
283
+ ```python
284
+ from pyagent_patterns.base import Agent
285
+ from pyagent_patterns.orchestration import Pipeline
286
+ from pyagent_providers import ProviderRegistry, CapabilityNegotiator
287
+ from pyagent_providers.adapters.mock import MockProvider
288
+
289
+ # Set up providers
290
+ registry = ProviderRegistry()
291
+ registry.register_sync(MockProvider(name="fast", responses=["Extracted facts"]))
292
+ registry.register_sync(MockProvider(name="smart", responses=["Detailed analysis"]))
293
+
294
+ # Use providers as Agent LLMs
295
+ fast = registry.get("fast")
296
+ smart = registry.get("smart")
297
+
298
+ pipeline = Pipeline(stages=[
299
+ Agent("extractor", fast, system_prompt="Extract key facts."),
300
+ Agent("analyst", smart, system_prompt="Analyse in depth."),
301
+ ])
302
+
303
+ result = asyncio.run(pipeline.run("Process this document"))
304
+ print(result.output)
305
+ ```
306
+
307
+ ## Full Documentation
308
+
309
+ See [pyagent.dev](https://pyagent.dev) for full API reference and integration guides.