requisite-ai 0.3.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.
- requisite_ai-0.3.0/LICENSE +21 -0
- requisite_ai-0.3.0/PKG-INFO +379 -0
- requisite_ai-0.3.0/README.md +348 -0
- requisite_ai-0.3.0/pyproject.toml +52 -0
- requisite_ai-0.3.0/requisite/__init__.py +116 -0
- requisite_ai-0.3.0/requisite/agents/__init__.py +6 -0
- requisite_ai-0.3.0/requisite/agents/agent.py +318 -0
- requisite_ai-0.3.0/requisite/agents/registry.py +66 -0
- requisite_ai-0.3.0/requisite/ai.py +329 -0
- requisite_ai-0.3.0/requisite/capabilities/__init__.py +28 -0
- requisite_ai-0.3.0/requisite/capabilities/registry.py +213 -0
- requisite_ai-0.3.0/requisite/capabilities/resolvers.py +166 -0
- requisite_ai-0.3.0/requisite/config/__init__.py +5 -0
- requisite_ai-0.3.0/requisite/config/settings.py +118 -0
- requisite_ai-0.3.0/requisite/core/__init__.py +1 -0
- requisite_ai-0.3.0/requisite/core/exceptions.py +116 -0
- requisite_ai-0.3.0/requisite/core/interfaces.py +193 -0
- requisite_ai-0.3.0/requisite/orchestrators/__init__.py +12 -0
- requisite_ai-0.3.0/requisite/orchestrators/base.py +92 -0
- requisite_ai-0.3.0/requisite/orchestrators/factory.py +101 -0
- requisite_ai-0.3.0/requisite/orchestrators/langgraph_orchestrator.py +148 -0
- requisite_ai-0.3.0/requisite/orchestrators/native.py +153 -0
- requisite_ai-0.3.0/requisite/providers/__init__.py +12 -0
- requisite_ai-0.3.0/requisite/providers/base.py +185 -0
- requisite_ai-0.3.0/requisite/providers/factory.py +155 -0
- requisite_ai-0.3.0/requisite/providers/gemini_provider.py +362 -0
- requisite_ai-0.3.0/requisite/providers/openai_provider.py +316 -0
- requisite_ai-0.3.0/requisite/py.typed +0 -0
- requisite_ai-0.3.0/requisite/skills/__init__.py +6 -0
- requisite_ai-0.3.0/requisite/skills/base.py +81 -0
- requisite_ai-0.3.0/requisite/skills/registry.py +64 -0
- requisite_ai-0.3.0/requisite/tools/__init__.py +7 -0
- requisite_ai-0.3.0/requisite/tools/base.py +136 -0
- requisite_ai-0.3.0/requisite/tools/decorator.py +77 -0
- requisite_ai-0.3.0/requisite/tools/registry.py +113 -0
- requisite_ai-0.3.0/requisite/tools/schema.py +107 -0
- requisite_ai-0.3.0/requisite/workflows/__init__.py +6 -0
- requisite_ai-0.3.0/requisite/workflows/workflow.py +169 -0
- requisite_ai-0.3.0/requisite_ai.egg-info/PKG-INFO +379 -0
- requisite_ai-0.3.0/requisite_ai.egg-info/SOURCES.txt +49 -0
- requisite_ai-0.3.0/requisite_ai.egg-info/dependency_links.txt +1 -0
- requisite_ai-0.3.0/requisite_ai.egg-info/requires.txt +23 -0
- requisite_ai-0.3.0/requisite_ai.egg-info/top_level.txt +1 -0
- requisite_ai-0.3.0/setup.cfg +4 -0
- requisite_ai-0.3.0/tests/test_agents.py +219 -0
- requisite_ai-0.3.0/tests/test_ai.py +188 -0
- requisite_ai-0.3.0/tests/test_capabilities.py +218 -0
- requisite_ai-0.3.0/tests/test_providers.py +285 -0
- requisite_ai-0.3.0/tests/test_settings.py +38 -0
- requisite_ai-0.3.0/tests/test_tools.py +113 -0
- requisite_ai-0.3.0/tests/test_workflows.py +159 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Requisite AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: requisite-ai
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: A provider-agnostic, plugin-based framework for building AI applications and agents. Declare what you need -- providers, tools, capabilities -- not which SDK provides it.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/requisite-ai/requisite-ai
|
|
7
|
+
Project-URL: Repository, https://github.com/requisite-ai/requisite-ai
|
|
8
|
+
Keywords: ai,agents,llm,openai,gemini,agentic,orchestration,mcp
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: pydantic>=2.7
|
|
13
|
+
Requires-Dist: pydantic-settings>=2.3
|
|
14
|
+
Provides-Extra: openai
|
|
15
|
+
Requires-Dist: openai>=1.35; extra == "openai"
|
|
16
|
+
Provides-Extra: gemini
|
|
17
|
+
Requires-Dist: google-genai>=1.0; extra == "gemini"
|
|
18
|
+
Provides-Extra: langgraph
|
|
19
|
+
Requires-Dist: langgraph>=0.2; extra == "langgraph"
|
|
20
|
+
Provides-Extra: all
|
|
21
|
+
Requires-Dist: openai>=1.35; extra == "all"
|
|
22
|
+
Requires-Dist: google-genai>=1.0; extra == "all"
|
|
23
|
+
Requires-Dist: langgraph>=0.2; extra == "all"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
29
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# Requisite
|
|
33
|
+
|
|
34
|
+
[](https://github.com/requisite-ai/requisite-ai/actions/workflows/ci.yml)
|
|
35
|
+
[](https://codecov.io/gh/requisite-ai/requisite-ai)
|
|
36
|
+
[](https://pypi.org/project/requisite-ai/)
|
|
37
|
+
[](LICENSE)
|
|
38
|
+
[](pyproject.toml)
|
|
39
|
+
|
|
40
|
+
**Declare what your AI application needs — not which SDK provides it.**
|
|
41
|
+
|
|
42
|
+
A provider-agnostic, plugin-based Python framework for building AI
|
|
43
|
+
applications and agents. Swap the LLM provider, the multi-agent execution
|
|
44
|
+
engine, or the implementation behind a capability like `"weather"` or
|
|
45
|
+
`"internet_search"` — all via configuration, never a rewrite.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from requisite import AI
|
|
49
|
+
|
|
50
|
+
ai = AI() # provider="openai" by default
|
|
51
|
+
ai = AI(provider="gemini", model="gemini-2.5-flash") # same API, different provider
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from requisite import Agent
|
|
56
|
+
|
|
57
|
+
agent = Agent(name="Assistant", provider="openai")
|
|
58
|
+
agent.requires("weather", "internet_search", "filesystem") # not use_tool(specific_impl)
|
|
59
|
+
agent.run("What's the weather in Tokyo?")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install -e .[all] # both providers + langgraph
|
|
66
|
+
pip install -e .[openai] # OpenAI only
|
|
67
|
+
pip install -e .[gemini] # Gemini only
|
|
68
|
+
pip install -e .[langgraph] # native + langgraph orchestration
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or with the plain requirements file: `pip install -r requirements.txt`
|
|
72
|
+
|
|
73
|
+
> **Note on the Gemini SDK:** this framework uses the current, unified
|
|
74
|
+
> `google-genai` package (`from google import genai`). Do not install the
|
|
75
|
+
> deprecated `google-generativeai` package — the two conflict.
|
|
76
|
+
|
|
77
|
+
## Configuration
|
|
78
|
+
|
|
79
|
+
Copy `.env.example` to `.env` and fill in the key(s) for the provider(s) you use:
|
|
80
|
+
|
|
81
|
+
```env
|
|
82
|
+
OPENAI_API_KEY=
|
|
83
|
+
GEMINI_API_KEY=
|
|
84
|
+
DEFAULT_PROVIDER=openai
|
|
85
|
+
MODEL=gpt-4o-mini
|
|
86
|
+
TEMPERATURE=0.2
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`Settings` (`requisite/config/settings.py`) reads this automatically — you
|
|
90
|
+
never call `os.environ.get` yourself.
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### Chat
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from requisite import AI
|
|
98
|
+
|
|
99
|
+
ai = AI()
|
|
100
|
+
print(ai.chat("Explain LangGraph in one sentence."))
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Structured output
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from pydantic import BaseModel
|
|
107
|
+
|
|
108
|
+
class Person(BaseModel):
|
|
109
|
+
name: str
|
|
110
|
+
age: int
|
|
111
|
+
|
|
112
|
+
person = ai.chat("Extract: John is 30 years old.", response_model=Person)
|
|
113
|
+
print(person.name, person.age) # John 30
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Tool calling
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from requisite.tools import tool
|
|
120
|
+
|
|
121
|
+
@tool
|
|
122
|
+
def get_weather(city: str) -> str:
|
|
123
|
+
"""Get the current weather for a city."""
|
|
124
|
+
return f"Sunny, 22C in {city}"
|
|
125
|
+
|
|
126
|
+
response = ai.chat_response("What's the weather in Paris?", tools=[get_weather])
|
|
127
|
+
if response.has_tool_calls:
|
|
128
|
+
call = response.tool_calls[0]
|
|
129
|
+
result = get_weather.tool.execute(**call.arguments)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
That's the low-level view. For most applications, let an `Agent` run the
|
|
133
|
+
full tool-calling loop for you (see below).
|
|
134
|
+
|
|
135
|
+
### Agents
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from requisite import Agent
|
|
139
|
+
from requisite.tools import tool
|
|
140
|
+
|
|
141
|
+
@tool
|
|
142
|
+
def get_weather(city: str) -> str:
|
|
143
|
+
"""Get the current weather for a city."""
|
|
144
|
+
return f"Sunny, 22C in {city}"
|
|
145
|
+
|
|
146
|
+
agent = Agent(name="Weather Agent", provider="openai", tools=[get_weather])
|
|
147
|
+
result = agent.run("What's the weather in Paris?")
|
|
148
|
+
print(result.content) # "It's sunny and 22C in Paris."
|
|
149
|
+
print(result.tool_calls_executed) # ["get_weather"]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`Agent` automatically: offers its tools/skills to the model, executes any
|
|
153
|
+
tool calls the model requests, feeds results back, and repeats (up to
|
|
154
|
+
`max_iterations`) until it has a final answer.
|
|
155
|
+
|
|
156
|
+
### Multi-agent workflows
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from requisite import Agent, Workflow
|
|
160
|
+
|
|
161
|
+
research = Agent(name="Researcher", provider="openai")
|
|
162
|
+
writer = Agent(name="Writer", provider="openai")
|
|
163
|
+
|
|
164
|
+
workflow = Workflow()
|
|
165
|
+
workflow.add(research)
|
|
166
|
+
workflow.add(writer)
|
|
167
|
+
|
|
168
|
+
result = workflow.run("Research AI trends and write a summary.")
|
|
169
|
+
print(result.content)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Run agents in parallel against the same input instead of as a pipeline:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
workflow.parallel()
|
|
176
|
+
result = workflow.run("What is retrieval-augmented generation?")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Switch the execution engine — the `.add()` / `.run()` API never changes:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
workflow.use_langgraph() # requires: pip install langgraph
|
|
183
|
+
result = workflow.run("Research AI trends and write a summary.")
|
|
184
|
+
|
|
185
|
+
workflow.use_native() # back to the built-in, dependency-free engine
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Skills
|
|
189
|
+
|
|
190
|
+
A skill is a reusable, higher-level capability (vs. a tool, which is
|
|
191
|
+
typically a single function). Skills expose themselves to the model as
|
|
192
|
+
tools automatically:
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from requisite.skills import BaseSkill
|
|
196
|
+
|
|
197
|
+
class ReadFileSkill(BaseSkill):
|
|
198
|
+
def __init__(self):
|
|
199
|
+
super().__init__(name="read_file", description="Read a text file's contents.")
|
|
200
|
+
|
|
201
|
+
def run(self, path: str) -> str:
|
|
202
|
+
with open(path) as f:
|
|
203
|
+
return f.read()
|
|
204
|
+
|
|
205
|
+
agent = Agent(name="File Agent", provider="openai", skills=[ReadFileSkill()])
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Capabilities: declare *what*, not *which*
|
|
209
|
+
|
|
210
|
+
`agent.use_tool(specific_impl)` binds an agent to one concrete
|
|
211
|
+
implementation at write-time. `agent.requires("weather")` binds it to a
|
|
212
|
+
*name*, resolved at runtime against whichever implementation is
|
|
213
|
+
currently available — a native tool, an MCP server, a cloud API, or a
|
|
214
|
+
third-party plugin:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from requisite import Agent
|
|
218
|
+
|
|
219
|
+
agent = Agent(name="Assistant", provider="openai")
|
|
220
|
+
agent.requires("weather", "internet_search", "filesystem")
|
|
221
|
+
|
|
222
|
+
result = agent.run("What's the weather in Tokyo?")
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Three capabilities ship out of the box, backed by free/keyless APIs and
|
|
226
|
+
the local filesystem (see `requisite/capabilities/resolvers.py`):
|
|
227
|
+
`"filesystem"`, `"weather"`, `"internet_search"`.
|
|
228
|
+
|
|
229
|
+
Register a better provider for the same capability at a higher priority
|
|
230
|
+
and it takes over automatically — application code never changes:
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
from requisite.capabilities import default_registry
|
|
234
|
+
|
|
235
|
+
default_registry.register(
|
|
236
|
+
"weather",
|
|
237
|
+
my_paid_weather_tool,
|
|
238
|
+
provider_name="acme-weather",
|
|
239
|
+
priority=10,
|
|
240
|
+
is_available=lambda: bool(os.environ.get("ACME_API_KEY")),
|
|
241
|
+
)
|
|
242
|
+
# agent.requires("weather") now resolves to "acme-weather" when the key
|
|
243
|
+
# is set, and quietly falls back to the built-in provider otherwise.
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
This is the same interface + registry pattern used for providers and
|
|
247
|
+
orchestrators, one layer up: `CapabilityRegistry.resolve(name)` picks the
|
|
248
|
+
highest-priority provider whose `is_available()` currently returns
|
|
249
|
+
`True`, raising `CapabilityException` if none are.
|
|
250
|
+
|
|
251
|
+
### Streaming & async
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
for token in ai.stream("Write a haiku about distributed systems."):
|
|
255
|
+
print(token, end="")
|
|
256
|
+
|
|
257
|
+
text = await ai.achat("Hello!")
|
|
258
|
+
async for token in ai.astream("Hello, streamed!"):
|
|
259
|
+
print(token, end="")
|
|
260
|
+
|
|
261
|
+
result = await agent.arun("What's the weather in Paris?")
|
|
262
|
+
result = await workflow.arun("Research AI trends.")
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Conversation history
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
from requisite import Message
|
|
269
|
+
|
|
270
|
+
history = [
|
|
271
|
+
Message.user("My name is Alex."),
|
|
272
|
+
Message.assistant("Nice to meet you, Alex!"),
|
|
273
|
+
Message.user("What's my name?"),
|
|
274
|
+
]
|
|
275
|
+
print(ai.chat(history))
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
See `examples/` for complete, runnable scripts covering each of the above.
|
|
279
|
+
|
|
280
|
+
## Architecture
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
requisite/
|
|
284
|
+
├── core/ # Provider-agnostic data models (Message, ChatResponse,
|
|
285
|
+
│ # ToolCall, ...) and the AIException hierarchy
|
|
286
|
+
├── config/ # Settings (pydantic-settings, reads .env)
|
|
287
|
+
├── providers/ # BaseProvider interface + OpenAI/Gemini implementations
|
|
288
|
+
│ # + ProviderRegistry (extensible, DI-friendly factory)
|
|
289
|
+
├── tools/ # Tool, @tool decorator, ToolRegistry, JSON Schema derivation
|
|
290
|
+
├── skills/ # BaseSkill, SkillRegistry -- reusable higher-level capabilities
|
|
291
|
+
├── capabilities/ # CapabilityRegistry -- resolve a named capability (e.g.
|
|
292
|
+
│ # "weather") to whichever implementation is available
|
|
293
|
+
├── agents/ # Agent (tool-calling loop, .requires()) + AgentRegistry
|
|
294
|
+
├── orchestrators/ # BaseOrchestrator interface + native (sequential/parallel)
|
|
295
|
+
│ # and langgraph backends + OrchestratorRegistry
|
|
296
|
+
├── workflows/ # Workflow -- the small, ergonomic multi-agent facade
|
|
297
|
+
└── ai.py # The `AI` facade -- the class most users touch directly
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Every layer follows the same pattern: a small abstract interface
|
|
301
|
+
(`BaseProvider`, `BaseOrchestrator`, ...), one or more concrete
|
|
302
|
+
implementations, and a plain, instantiable registry (not a singleton)
|
|
303
|
+
mapping names to constructors. That's what makes each of the following a
|
|
304
|
+
*configuration* change rather than a *code* change:
|
|
305
|
+
|
|
306
|
+
- `AI(provider="openai")` → `AI(provider="gemini")`
|
|
307
|
+
- `Workflow(orchestrator="native")` → `workflow.use_langgraph()`
|
|
308
|
+
- `agent.use_tool(specific_impl)` → `agent.requires("weather")`
|
|
309
|
+
|
|
310
|
+
See **[`ARCHITECTURE.md`](ARCHITECTURE.md)** for the full dependency
|
|
311
|
+
diagram, request-flow walkthroughs (a chat call, an agent's tool-calling
|
|
312
|
+
loop, capability resolution, a multi-agent workflow), and the design
|
|
313
|
+
decisions behind them. See **[`CONTRIBUTING.md`](CONTRIBUTING.md)** for
|
|
314
|
+
the step-by-step to add a new provider, orchestrator backend, or
|
|
315
|
+
capability resolver.
|
|
316
|
+
|
|
317
|
+
## Error handling
|
|
318
|
+
|
|
319
|
+
All framework exceptions inherit from `AIException`:
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
AIException
|
|
323
|
+
├── ConfigurationException # missing/invalid config, unknown provider/orchestrator name
|
|
324
|
+
├── ProviderException # provider SDK call failed (wraps the original error)
|
|
325
|
+
├── ToolException # a tool wasn't found, or raised while executing
|
|
326
|
+
├── SkillException # a skill wasn't found, or raised while executing
|
|
327
|
+
├── AgentException # agent execution failed (e.g. max_iterations exceeded)
|
|
328
|
+
├── CapabilityException # a required capability has no available provider
|
|
329
|
+
└── MCPException # reserved for the upcoming MCP integration
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Provider SDK errors are never swallowed — they're wrapped with `provider`
|
|
333
|
+
and `original_error` attached, and re-raised via `raise ... from original_error`
|
|
334
|
+
so the original traceback is preserved.
|
|
335
|
+
|
|
336
|
+
## Testing
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
pytest
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Tests never hit the network: the OpenAI and Gemini SDKs are faked via
|
|
343
|
+
`sys.modules` injection, and the `AI` / `Agent` / `Workflow` facades are
|
|
344
|
+
tested against fully in-memory fake providers.
|
|
345
|
+
|
|
346
|
+
## Roadmap
|
|
347
|
+
|
|
348
|
+
Implemented: provider connectivity (OpenAI, Gemini), structured outputs,
|
|
349
|
+
tool calling, skills, capability resolution (`agent.requires(...)`),
|
|
350
|
+
agents + registry, multi-agent workflows (sequential/parallel, native +
|
|
351
|
+
langgraph backends).
|
|
352
|
+
|
|
353
|
+
See [`ROADMAP.md`](ROADMAP.md) for the full, per-layer status table
|
|
354
|
+
(providers, orchestration strategies, MCP, memory, RAG, ...) and what's
|
|
355
|
+
explicitly out of scope.
|
|
356
|
+
|
|
357
|
+
## Contributing
|
|
358
|
+
|
|
359
|
+
Contributions are welcome:
|
|
360
|
+
|
|
361
|
+
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — dev setup, running checks, and
|
|
362
|
+
step-by-step guides for adding a provider, orchestrator backend, or
|
|
363
|
+
capability resolver.
|
|
364
|
+
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — how the framework fits together
|
|
365
|
+
and why: the interface + registry pattern, request-flow walkthroughs,
|
|
366
|
+
design decisions.
|
|
367
|
+
- [`DEVELOPMENT.md`](DEVELOPMENT.md) — coding standards, testing
|
|
368
|
+
philosophy, docstring format, logging/error-handling conventions,
|
|
369
|
+
versioning policy.
|
|
370
|
+
- [`ROADMAP.md`](ROADMAP.md) — what's shipped, planned, or out of scope.
|
|
371
|
+
|
|
372
|
+
Please also read the [Code of Conduct](CODE_OF_CONDUCT.md). Security
|
|
373
|
+
issues should go through [`SECURITY.md`](SECURITY.md), not a public issue.
|
|
374
|
+
|
|
375
|
+
See [`CHANGELOG.md`](CHANGELOG.md) for release history.
|
|
376
|
+
|
|
377
|
+
## License
|
|
378
|
+
|
|
379
|
+
MIT — see [`LICENSE`](LICENSE).
|