agent-framework-typesafe 1.0.0a261002__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.
- agent_framework_typesafe-1.0.0a261002/LICENSE +21 -0
- agent_framework_typesafe-1.0.0a261002/PKG-INFO +240 -0
- agent_framework_typesafe-1.0.0a261002/README.md +212 -0
- agent_framework_typesafe-1.0.0a261002/agent_framework_typesafe/__init__.py +17 -0
- agent_framework_typesafe-1.0.0a261002/agent_framework_typesafe/_chat_client.py +681 -0
- agent_framework_typesafe-1.0.0a261002/agent_framework_typesafe/_tool_calls.py +649 -0
- agent_framework_typesafe-1.0.0a261002/agent_framework_typesafe/py.typed +0 -0
- agent_framework_typesafe-1.0.0a261002/pyproject.toml +105 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation.
|
|
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,240 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-framework-typesafe
|
|
3
|
+
Version: 1.0.0a261002
|
|
4
|
+
Summary: TypeSafe AI integration for Microsoft Agent Framework.
|
|
5
|
+
Author: Microsoft
|
|
6
|
+
Author-email: Microsoft <af-support@microsoft.com>
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Framework :: Pydantic :: 2
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: agent-framework-core>=1.19.0,<2
|
|
20
|
+
Requires-Dist: httpx2>=2.0.0,<3
|
|
21
|
+
Requires-Dist: typesafe-sdk>=0.7.1,<0.8.0
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Project-URL: homepage, https://aka.ms/agent-framework
|
|
24
|
+
Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
|
|
25
|
+
Project-URL: release_notes, https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true
|
|
26
|
+
Project-URL: issues, https://github.com/microsoft/agent-framework/issues
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# Agent Framework TypeSafe AI
|
|
30
|
+
|
|
31
|
+
Use [TypeSafe AI](https://docs.typesafe.ai/) System One models, including Jev,
|
|
32
|
+
with Microsoft Agent Framework.
|
|
33
|
+
|
|
34
|
+
This alpha package adapts TypeSafe's structured decision API to the Agent Framework
|
|
35
|
+
chat client contract. Jev evaluates
|
|
36
|
+
[application state](https://docs.typesafe.ai/concepts/state.md) against explicit
|
|
37
|
+
[typed questions](https://docs.typesafe.ai/primitives.md) and returns
|
|
38
|
+
probabilities and scores. It does not generate ordinary chat text.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install agent-framework-typesafe --pre
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
Set `TYPESAFE_API_KEY`, then create TypeSafe questions and run them through an
|
|
49
|
+
Agent Framework `Agent`:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from agent_framework import Agent
|
|
53
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
54
|
+
from typesafe_sdk import Choice, Noul
|
|
55
|
+
|
|
56
|
+
client = TypeSafeChatClient()
|
|
57
|
+
try:
|
|
58
|
+
agent = Agent(
|
|
59
|
+
client=client,
|
|
60
|
+
name="TicketEvaluator",
|
|
61
|
+
instructions="Evaluate the support request using the configured questions.",
|
|
62
|
+
)
|
|
63
|
+
response = await agent.run(
|
|
64
|
+
"Our checkout has failed for three days and we are losing sales.",
|
|
65
|
+
options={
|
|
66
|
+
"response_format": {
|
|
67
|
+
"department": Choice(
|
|
68
|
+
instructions="Which team should handle this request?",
|
|
69
|
+
criteria={"billing": None, "technical": None, "sales": None},
|
|
70
|
+
),
|
|
71
|
+
"urgent": Noul(instructions="Does this request need urgent attention?"),
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
)
|
|
75
|
+
print(response.value)
|
|
76
|
+
finally:
|
|
77
|
+
await client.close()
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For this connector, Agent Framework's `response_format` option is the TypeSafe
|
|
81
|
+
[`Questions`](https://docs.typesafe.ai/sdk/python/api/types/questions.md)
|
|
82
|
+
mapping. The connector forwards it as the SDK's `questions` argument and
|
|
83
|
+
internally uses
|
|
84
|
+
[`SystemOneResponse`](https://docs.typesafe.ai/sdk/python/api/types/responses.md)
|
|
85
|
+
as the actual response model.
|
|
86
|
+
|
|
87
|
+
`AgentLoopMiddleware.with_judge(...)` supports provider-specific structured
|
|
88
|
+
judges through its `response_format` and `verdict_parser` arguments. Pass a
|
|
89
|
+
TypeSafe `Questions` mapping as the response format and convert the returned
|
|
90
|
+
`SystemOneResponse` into the framework's `JudgeVerdict` in the loop setup. This
|
|
91
|
+
keeps the connector focused on TypeSafe response primitives instead of making
|
|
92
|
+
it aware of framework-specific judge models.
|
|
93
|
+
|
|
94
|
+
Framework integrations with a fixed TypeSafe contract can configure
|
|
95
|
+
`default_questions` on the client and omit per-call `response_format`. For
|
|
96
|
+
example, `SecureAgentConfig` can use
|
|
97
|
+
`TypeSafeChatClient(default_questions=quarantine_questions)` directly as its
|
|
98
|
+
quarantine client; the framework's explicit `tool_choice="none"` forwarding is
|
|
99
|
+
honored.
|
|
100
|
+
|
|
101
|
+
## Supported options
|
|
102
|
+
|
|
103
|
+
| Option | Description |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| `response_format` | Required non-empty TypeSafe `Questions` mapping containing `Noul`, `Choice`, or `Score` questions. |
|
|
106
|
+
| `model` | Optional per-call model override. |
|
|
107
|
+
| `instructions` | Agent instructions included in the structured state sent to TypeSafe. |
|
|
108
|
+
|
|
109
|
+
Streaming, non-text message content, and generative settings such as `temperature`
|
|
110
|
+
are rejected.
|
|
111
|
+
|
|
112
|
+
`TypeSafeChatClient` is the recommended client and layers function invocation,
|
|
113
|
+
middleware, and telemetry over `RawTypeSafeChatClient`. Use the raw client only
|
|
114
|
+
when composing a custom layer stack or intentionally opting out of those framework
|
|
115
|
+
layers. The raw client can inspect compatible tools and emit Agent Framework
|
|
116
|
+
function calls, but it does not execute them itself.
|
|
117
|
+
|
|
118
|
+
## Function calling
|
|
119
|
+
|
|
120
|
+
TypeSafe converts tool selection and supported arguments into internal `Choice`
|
|
121
|
+
and `Noul` questions, emits Agent Framework function calls, and lets the standard
|
|
122
|
+
function-invocation loop execute them. The client defaults to one tool call per
|
|
123
|
+
run; opt into sequential round trips with
|
|
124
|
+
`function_invocation_configuration={"max_function_calls": N}`. Jev can select
|
|
125
|
+
another tool call after seeing each result, or select no tool to finish.
|
|
126
|
+
|
|
127
|
+
This follows TypeSafe's
|
|
128
|
+
[Function calling cookbook](https://docs.typesafe.ai/cookbooks/function_calling.md):
|
|
129
|
+
the model selects from closed sets, while application code owns validation and
|
|
130
|
+
execution.
|
|
131
|
+
|
|
132
|
+
The terminal response text consolidates the current turn's tool results and any
|
|
133
|
+
final TypeSafe `Choice` or `Score` decisions. The full terminal
|
|
134
|
+
`SystemOneResponse`, including `Noul` answers, remains available through
|
|
135
|
+
`response.value`.
|
|
136
|
+
|
|
137
|
+
Supported input-schema shapes:
|
|
138
|
+
|
|
139
|
+
- Empty/zero-argument object schemas.
|
|
140
|
+
- Fixed `const` values.
|
|
141
|
+
- `enum` or Python `Literal` arguments.
|
|
142
|
+
- Boolean arguments.
|
|
143
|
+
- Arrays whose items are `enum` or `Literal` values. These are treated as
|
|
144
|
+
set-like selections in schema order; duplicates and caller-defined ordering are
|
|
145
|
+
not supported. Arrays with `minItems`, `maxItems`, uniqueness, prefix, or
|
|
146
|
+
membership constraints are rejected because the connector cannot preserve those
|
|
147
|
+
semantics. Every enum member must match the declared item type.
|
|
148
|
+
- Optional versions of those shapes. A separate TypeSafe question decides whether
|
|
149
|
+
to omit the argument so the function's default can apply.
|
|
150
|
+
|
|
151
|
+
Required free-form strings, numbers, nested objects, general arrays, and required
|
|
152
|
+
nullable arguments are not supported. Schema constraints that the connector
|
|
153
|
+
cannot preserve, such as `allOf` on the root object, an argument, or an array
|
|
154
|
+
item, also exclude the entire tool. Assertion siblings beside `$ref` or nullable
|
|
155
|
+
`anyOf` are rejected rather than merged in a way that could broaden the schema.
|
|
156
|
+
A tool is excluded when any declared argument is unsupported, including optional
|
|
157
|
+
arguments, so invocation never falls back to an unintended default. In automatic
|
|
158
|
+
tool mode, unsupported tools are excluded with a warning. Required unsupported
|
|
159
|
+
tools fail the request.
|
|
160
|
+
|
|
161
|
+
Local tools can use inferred schemas or Pydantic input models:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from typing import Literal
|
|
165
|
+
|
|
166
|
+
from agent_framework import Agent, FunctionTool
|
|
167
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
168
|
+
from pydantic import BaseModel
|
|
169
|
+
from typesafe_sdk import Noul
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class WeatherArguments(BaseModel):
|
|
173
|
+
city: Literal["Seattle", "Paris"]
|
|
174
|
+
detailed: bool
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
weather = FunctionTool(
|
|
178
|
+
name="weather",
|
|
179
|
+
description="Get weather for a supported city.",
|
|
180
|
+
func=lambda city, detailed: f"Weather for {city}; detailed={detailed}",
|
|
181
|
+
input_model=WeatherArguments,
|
|
182
|
+
)
|
|
183
|
+
agent = Agent(client=TypeSafeChatClient(), tools=[weather])
|
|
184
|
+
response = await agent.run(
|
|
185
|
+
"Give me detailed Seattle weather.",
|
|
186
|
+
options={"response_format": {"succeeded": Noul(instructions="Did the tool result indicate success?")}},
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
MCP tools are supported through `Agent`, which connects to the server and expands
|
|
191
|
+
discovered MCP functions into `FunctionTool` objects before TypeSafe routing:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from agent_framework import Agent, MCPStdioTool
|
|
195
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
196
|
+
|
|
197
|
+
mcp = MCPStdioTool(name="my-server", command="my-mcp-server")
|
|
198
|
+
agent = Agent(client=TypeSafeChatClient(), tools=[mcp])
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Only discovered MCP functions whose JSON schemas fit the supported subset are
|
|
202
|
+
routable. Use `tool_choice.allowed_tools` to narrow large MCP servers; a request
|
|
203
|
+
supports at most 32 routable tools, 64 properties per tool, 64 enum members per
|
|
204
|
+
argument, and 128 generated internal questions. The routable-tool limit is
|
|
205
|
+
checked after tool-choice filtering and before any tool schemas are compiled. An
|
|
206
|
+
exact cumulative question budget is reserved before question objects are
|
|
207
|
+
constructed, so schemas that would exceed 128 questions fail without
|
|
208
|
+
materializing the excess. An explicitly empty `allowed_tools` list denies every
|
|
209
|
+
tool. Routing criteria always include the exact function name and its optional
|
|
210
|
+
description so identically described tools remain distinguishable.
|
|
211
|
+
|
|
212
|
+
## Configuration and lifecycle
|
|
213
|
+
|
|
214
|
+
The internally created TypeSafe SDK client reads:
|
|
215
|
+
|
|
216
|
+
- `TYPESAFE_API_KEY` - required API key.
|
|
217
|
+
- `TYPESAFE_DEFAULT_MODEL` - optional default model; the SDK defaults to `jev-latest`.
|
|
218
|
+
- `TYPESAFE_BASE_URL` - optional API root override.
|
|
219
|
+
|
|
220
|
+
Constructor values take precedence over an explicitly selected `.env` file and
|
|
221
|
+
process environment variables. Credential requirements are evaluated only after
|
|
222
|
+
those sources are resolved. When `async_client` is supplied, the injected client
|
|
223
|
+
is authoritative and no API key, endpoint, or environment-resolved model is
|
|
224
|
+
applied by the connector. An explicitly passed per-request or constructor `model`
|
|
225
|
+
can still override the injected client's default.
|
|
226
|
+
|
|
227
|
+
For advanced SDK configuration, inject a configured `AsyncTypeSafeClient`:
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
231
|
+
from typesafe_sdk import AsyncTypeSafeClient
|
|
232
|
+
|
|
233
|
+
sdk_client = AsyncTypeSafeClient(timeout=60)
|
|
234
|
+
client = TypeSafeChatClient(async_client=sdk_client)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Injected SDK clients remain caller-owned. Use `close()` or `async with` to close
|
|
238
|
+
clients created by `TypeSafeChatClient`.
|
|
239
|
+
|
|
240
|
+
See the [package sample](samples/README.md) for a runnable direct-client and Agent example.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Agent Framework TypeSafe AI
|
|
2
|
+
|
|
3
|
+
Use [TypeSafe AI](https://docs.typesafe.ai/) System One models, including Jev,
|
|
4
|
+
with Microsoft Agent Framework.
|
|
5
|
+
|
|
6
|
+
This alpha package adapts TypeSafe's structured decision API to the Agent Framework
|
|
7
|
+
chat client contract. Jev evaluates
|
|
8
|
+
[application state](https://docs.typesafe.ai/concepts/state.md) against explicit
|
|
9
|
+
[typed questions](https://docs.typesafe.ai/primitives.md) and returns
|
|
10
|
+
probabilities and scores. It does not generate ordinary chat text.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install agent-framework-typesafe --pre
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
Set `TYPESAFE_API_KEY`, then create TypeSafe questions and run them through an
|
|
21
|
+
Agent Framework `Agent`:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from agent_framework import Agent
|
|
25
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
26
|
+
from typesafe_sdk import Choice, Noul
|
|
27
|
+
|
|
28
|
+
client = TypeSafeChatClient()
|
|
29
|
+
try:
|
|
30
|
+
agent = Agent(
|
|
31
|
+
client=client,
|
|
32
|
+
name="TicketEvaluator",
|
|
33
|
+
instructions="Evaluate the support request using the configured questions.",
|
|
34
|
+
)
|
|
35
|
+
response = await agent.run(
|
|
36
|
+
"Our checkout has failed for three days and we are losing sales.",
|
|
37
|
+
options={
|
|
38
|
+
"response_format": {
|
|
39
|
+
"department": Choice(
|
|
40
|
+
instructions="Which team should handle this request?",
|
|
41
|
+
criteria={"billing": None, "technical": None, "sales": None},
|
|
42
|
+
),
|
|
43
|
+
"urgent": Noul(instructions="Does this request need urgent attention?"),
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
)
|
|
47
|
+
print(response.value)
|
|
48
|
+
finally:
|
|
49
|
+
await client.close()
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For this connector, Agent Framework's `response_format` option is the TypeSafe
|
|
53
|
+
[`Questions`](https://docs.typesafe.ai/sdk/python/api/types/questions.md)
|
|
54
|
+
mapping. The connector forwards it as the SDK's `questions` argument and
|
|
55
|
+
internally uses
|
|
56
|
+
[`SystemOneResponse`](https://docs.typesafe.ai/sdk/python/api/types/responses.md)
|
|
57
|
+
as the actual response model.
|
|
58
|
+
|
|
59
|
+
`AgentLoopMiddleware.with_judge(...)` supports provider-specific structured
|
|
60
|
+
judges through its `response_format` and `verdict_parser` arguments. Pass a
|
|
61
|
+
TypeSafe `Questions` mapping as the response format and convert the returned
|
|
62
|
+
`SystemOneResponse` into the framework's `JudgeVerdict` in the loop setup. This
|
|
63
|
+
keeps the connector focused on TypeSafe response primitives instead of making
|
|
64
|
+
it aware of framework-specific judge models.
|
|
65
|
+
|
|
66
|
+
Framework integrations with a fixed TypeSafe contract can configure
|
|
67
|
+
`default_questions` on the client and omit per-call `response_format`. For
|
|
68
|
+
example, `SecureAgentConfig` can use
|
|
69
|
+
`TypeSafeChatClient(default_questions=quarantine_questions)` directly as its
|
|
70
|
+
quarantine client; the framework's explicit `tool_choice="none"` forwarding is
|
|
71
|
+
honored.
|
|
72
|
+
|
|
73
|
+
## Supported options
|
|
74
|
+
|
|
75
|
+
| Option | Description |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| `response_format` | Required non-empty TypeSafe `Questions` mapping containing `Noul`, `Choice`, or `Score` questions. |
|
|
78
|
+
| `model` | Optional per-call model override. |
|
|
79
|
+
| `instructions` | Agent instructions included in the structured state sent to TypeSafe. |
|
|
80
|
+
|
|
81
|
+
Streaming, non-text message content, and generative settings such as `temperature`
|
|
82
|
+
are rejected.
|
|
83
|
+
|
|
84
|
+
`TypeSafeChatClient` is the recommended client and layers function invocation,
|
|
85
|
+
middleware, and telemetry over `RawTypeSafeChatClient`. Use the raw client only
|
|
86
|
+
when composing a custom layer stack or intentionally opting out of those framework
|
|
87
|
+
layers. The raw client can inspect compatible tools and emit Agent Framework
|
|
88
|
+
function calls, but it does not execute them itself.
|
|
89
|
+
|
|
90
|
+
## Function calling
|
|
91
|
+
|
|
92
|
+
TypeSafe converts tool selection and supported arguments into internal `Choice`
|
|
93
|
+
and `Noul` questions, emits Agent Framework function calls, and lets the standard
|
|
94
|
+
function-invocation loop execute them. The client defaults to one tool call per
|
|
95
|
+
run; opt into sequential round trips with
|
|
96
|
+
`function_invocation_configuration={"max_function_calls": N}`. Jev can select
|
|
97
|
+
another tool call after seeing each result, or select no tool to finish.
|
|
98
|
+
|
|
99
|
+
This follows TypeSafe's
|
|
100
|
+
[Function calling cookbook](https://docs.typesafe.ai/cookbooks/function_calling.md):
|
|
101
|
+
the model selects from closed sets, while application code owns validation and
|
|
102
|
+
execution.
|
|
103
|
+
|
|
104
|
+
The terminal response text consolidates the current turn's tool results and any
|
|
105
|
+
final TypeSafe `Choice` or `Score` decisions. The full terminal
|
|
106
|
+
`SystemOneResponse`, including `Noul` answers, remains available through
|
|
107
|
+
`response.value`.
|
|
108
|
+
|
|
109
|
+
Supported input-schema shapes:
|
|
110
|
+
|
|
111
|
+
- Empty/zero-argument object schemas.
|
|
112
|
+
- Fixed `const` values.
|
|
113
|
+
- `enum` or Python `Literal` arguments.
|
|
114
|
+
- Boolean arguments.
|
|
115
|
+
- Arrays whose items are `enum` or `Literal` values. These are treated as
|
|
116
|
+
set-like selections in schema order; duplicates and caller-defined ordering are
|
|
117
|
+
not supported. Arrays with `minItems`, `maxItems`, uniqueness, prefix, or
|
|
118
|
+
membership constraints are rejected because the connector cannot preserve those
|
|
119
|
+
semantics. Every enum member must match the declared item type.
|
|
120
|
+
- Optional versions of those shapes. A separate TypeSafe question decides whether
|
|
121
|
+
to omit the argument so the function's default can apply.
|
|
122
|
+
|
|
123
|
+
Required free-form strings, numbers, nested objects, general arrays, and required
|
|
124
|
+
nullable arguments are not supported. Schema constraints that the connector
|
|
125
|
+
cannot preserve, such as `allOf` on the root object, an argument, or an array
|
|
126
|
+
item, also exclude the entire tool. Assertion siblings beside `$ref` or nullable
|
|
127
|
+
`anyOf` are rejected rather than merged in a way that could broaden the schema.
|
|
128
|
+
A tool is excluded when any declared argument is unsupported, including optional
|
|
129
|
+
arguments, so invocation never falls back to an unintended default. In automatic
|
|
130
|
+
tool mode, unsupported tools are excluded with a warning. Required unsupported
|
|
131
|
+
tools fail the request.
|
|
132
|
+
|
|
133
|
+
Local tools can use inferred schemas or Pydantic input models:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
from typing import Literal
|
|
137
|
+
|
|
138
|
+
from agent_framework import Agent, FunctionTool
|
|
139
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
140
|
+
from pydantic import BaseModel
|
|
141
|
+
from typesafe_sdk import Noul
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class WeatherArguments(BaseModel):
|
|
145
|
+
city: Literal["Seattle", "Paris"]
|
|
146
|
+
detailed: bool
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
weather = FunctionTool(
|
|
150
|
+
name="weather",
|
|
151
|
+
description="Get weather for a supported city.",
|
|
152
|
+
func=lambda city, detailed: f"Weather for {city}; detailed={detailed}",
|
|
153
|
+
input_model=WeatherArguments,
|
|
154
|
+
)
|
|
155
|
+
agent = Agent(client=TypeSafeChatClient(), tools=[weather])
|
|
156
|
+
response = await agent.run(
|
|
157
|
+
"Give me detailed Seattle weather.",
|
|
158
|
+
options={"response_format": {"succeeded": Noul(instructions="Did the tool result indicate success?")}},
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
MCP tools are supported through `Agent`, which connects to the server and expands
|
|
163
|
+
discovered MCP functions into `FunctionTool` objects before TypeSafe routing:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from agent_framework import Agent, MCPStdioTool
|
|
167
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
168
|
+
|
|
169
|
+
mcp = MCPStdioTool(name="my-server", command="my-mcp-server")
|
|
170
|
+
agent = Agent(client=TypeSafeChatClient(), tools=[mcp])
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Only discovered MCP functions whose JSON schemas fit the supported subset are
|
|
174
|
+
routable. Use `tool_choice.allowed_tools` to narrow large MCP servers; a request
|
|
175
|
+
supports at most 32 routable tools, 64 properties per tool, 64 enum members per
|
|
176
|
+
argument, and 128 generated internal questions. The routable-tool limit is
|
|
177
|
+
checked after tool-choice filtering and before any tool schemas are compiled. An
|
|
178
|
+
exact cumulative question budget is reserved before question objects are
|
|
179
|
+
constructed, so schemas that would exceed 128 questions fail without
|
|
180
|
+
materializing the excess. An explicitly empty `allowed_tools` list denies every
|
|
181
|
+
tool. Routing criteria always include the exact function name and its optional
|
|
182
|
+
description so identically described tools remain distinguishable.
|
|
183
|
+
|
|
184
|
+
## Configuration and lifecycle
|
|
185
|
+
|
|
186
|
+
The internally created TypeSafe SDK client reads:
|
|
187
|
+
|
|
188
|
+
- `TYPESAFE_API_KEY` - required API key.
|
|
189
|
+
- `TYPESAFE_DEFAULT_MODEL` - optional default model; the SDK defaults to `jev-latest`.
|
|
190
|
+
- `TYPESAFE_BASE_URL` - optional API root override.
|
|
191
|
+
|
|
192
|
+
Constructor values take precedence over an explicitly selected `.env` file and
|
|
193
|
+
process environment variables. Credential requirements are evaluated only after
|
|
194
|
+
those sources are resolved. When `async_client` is supplied, the injected client
|
|
195
|
+
is authoritative and no API key, endpoint, or environment-resolved model is
|
|
196
|
+
applied by the connector. An explicitly passed per-request or constructor `model`
|
|
197
|
+
can still override the injected client's default.
|
|
198
|
+
|
|
199
|
+
For advanced SDK configuration, inject a configured `AsyncTypeSafeClient`:
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from agent_framework_typesafe import TypeSafeChatClient
|
|
203
|
+
from typesafe_sdk import AsyncTypeSafeClient
|
|
204
|
+
|
|
205
|
+
sdk_client = AsyncTypeSafeClient(timeout=60)
|
|
206
|
+
client = TypeSafeChatClient(async_client=sdk_client)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Injected SDK clients remain caller-owned. Use `close()` or `async with` to close
|
|
210
|
+
clients created by `TypeSafeChatClient`.
|
|
211
|
+
|
|
212
|
+
See the [package sample](samples/README.md) for a runnable direct-client and Agent example.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import importlib.metadata
|
|
4
|
+
|
|
5
|
+
from ._chat_client import RawTypeSafeChatClient, TypeSafeChatClient, TypeSafeChatOptions
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
__version__ = importlib.metadata.version(__name__)
|
|
9
|
+
except importlib.metadata.PackageNotFoundError:
|
|
10
|
+
__version__ = "0.0.0"
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"RawTypeSafeChatClient",
|
|
14
|
+
"TypeSafeChatClient",
|
|
15
|
+
"TypeSafeChatOptions",
|
|
16
|
+
"__version__",
|
|
17
|
+
]
|