veris-ai 1.8.2__py3-none-any.whl → 1.9.0__py3-none-any.whl

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.

Potentially problematic release.


This version of veris-ai might be problematic. Click here for more details.

veris_ai/__init__.py CHANGED
@@ -6,42 +6,31 @@ __version__ = "0.1.0"
6
6
 
7
7
  # Import lightweight modules that only use base dependencies
8
8
  from .jaeger_interface import JaegerClient
9
- from .models import ResponseExpectation
9
+ from .models import ResponseExpectation, ToolCallOptions
10
10
  from .observability import init_observability, instrument_fastapi_app
11
11
  from .tool_mock import veris
12
12
 
13
13
  # Lazy import for modules with heavy dependencies
14
- _veris_runner = None
14
+ _Runner = None
15
15
  _VerisConfig = None
16
16
 
17
17
 
18
- def veris_runner(*args: Any, **kwargs: Any) -> Any: # noqa: ANN401
19
- """Lazy loader for the veris_runner function from agents_wrapper.
20
-
21
- This function wraps OpenAI agents Runner.run to intercept tool calls
22
- through the Veris SDK's mocking infrastructure.
23
-
24
- This function requires the 'agents' extra dependencies:
25
- pip install veris-ai[agents]
26
- """
27
- global _veris_runner # noqa: PLW0603
28
- if _veris_runner is None:
29
- try:
30
- from .agents_wrapper import veris_runner as _veris_runner_impl # noqa: PLC0415
31
-
32
- _veris_runner = _veris_runner_impl
33
- except ImportError as e:
34
- error_msg = (
35
- "The 'veris_runner' function requires additional dependencies. "
36
- "Please install them with: pip install veris-ai[agents]"
37
- )
38
- raise ImportError(error_msg) from e
39
- return _veris_runner(*args, **kwargs)
40
-
41
-
42
18
  def __getattr__(name: str) -> Any: # noqa: ANN401
43
- """Lazy load VerisConfig class."""
44
- global _VerisConfig # noqa: PLW0603
19
+ """Lazy load Runner and VerisConfig classes."""
20
+ global _Runner, _VerisConfig # noqa: PLW0603
21
+ if name == "Runner":
22
+ if _Runner is None:
23
+ try:
24
+ from .agents_wrapper import Runner as _Runner_impl # noqa: PLC0415
25
+
26
+ _Runner = _Runner_impl
27
+ except ImportError as e:
28
+ error_msg = (
29
+ "The 'Runner' class requires additional dependencies. "
30
+ "Please install them with: pip install veris-ai[agents]"
31
+ )
32
+ raise ImportError(error_msg) from e
33
+ return _Runner
45
34
  if name == "VerisConfig":
46
35
  if _VerisConfig is None:
47
36
  try:
@@ -63,8 +52,9 @@ __all__ = [
63
52
  "veris",
64
53
  "JaegerClient",
65
54
  "ResponseExpectation",
55
+ "ToolCallOptions",
66
56
  "init_observability",
67
57
  "instrument_fastapi_app",
68
- "veris_runner",
58
+ "Runner",
69
59
  "VerisConfig",
70
60
  ]
@@ -4,11 +4,12 @@ import logging
4
4
  from collections.abc import Callable
5
5
  from typing import Any
6
6
 
7
- from agents import RunContextWrapper, RunResult, Runner
7
+ from agents import RunContextWrapper, RunResult, Runner as OpenAIRunner
8
8
  from pydantic import BaseModel
9
9
 
10
10
  from veris_ai import veris
11
11
  from veris_ai.tool_mock import mock_tool_call
12
+ from veris_ai.models import ToolCallOptions
12
13
 
13
14
  logger = logging.getLogger(__name__)
14
15
 
@@ -16,6 +17,7 @@ logger = logging.getLogger(__name__)
16
17
  def _wrap(
17
18
  include_tools: list[str] | None = None,
18
19
  exclude_tools: list[str] | None = None,
20
+ tool_options: dict[str, ToolCallOptions] | None = None,
19
21
  ) -> Callable:
20
22
  """Private wrapper for OpenAI agents Runner to intercept tool calls through Veris SDK.
21
23
 
@@ -25,6 +27,7 @@ def _wrap(
25
27
  Args:
26
28
  include_tools: Optional list of tool names to intercept (only these if provided)
27
29
  exclude_tools: Optional list of tool names to NOT intercept (these run normally)
30
+ tool_options: Optional per-tool configuration for mocking behavior
28
31
 
29
32
  Returns:
30
33
  A wrapped Runner.run function
@@ -36,6 +39,8 @@ def _wrap(
36
39
  if include_tools and exclude_tools:
37
40
  msg = "Cannot specify both include_tools and exclude_tools"
38
41
  raise ValueError(msg)
42
+ if not tool_options:
43
+ tool_options = {}
39
44
 
40
45
  def wrapped_run_func(run_func: Callable) -> Callable:
41
46
  """Inner wrapper that takes the actual Runner.run function."""
@@ -68,7 +73,7 @@ def _wrap(
68
73
  original_on_invoke = tool.on_invoke_tool
69
74
 
70
75
  def make_wrapped_on_invoke_tool(
71
- tool_id: int, orig_invoke: Callable
76
+ tool_id: int, orig_invoke: Callable, tool_name_inner: str
72
77
  ) -> Callable:
73
78
  """Create a wrapped on_invoke_tool with proper closure."""
74
79
 
@@ -81,7 +86,10 @@ def _wrap(
81
86
  if the_func and session_id:
82
87
  # mock_tool_call is synchronous, don't await it
83
88
  return mock_tool_call(
84
- the_func, session_id, parameters, None
89
+ the_func,
90
+ session_id,
91
+ parameters,
92
+ tool_options.get(tool_name_inner),
85
93
  )
86
94
  # Fall back to original if we couldn't extract the function
87
95
  return await orig_invoke(ctx, parameters)
@@ -89,7 +97,7 @@ def _wrap(
89
97
  return wrapped_on_invoke_tool
90
98
 
91
99
  tool.on_invoke_tool = make_wrapped_on_invoke_tool(
92
- id(tool), original_on_invoke
100
+ id(tool), original_on_invoke, tool_name
93
101
  )
94
102
  return await run_func(starting_agent, input_text, **kwargs)
95
103
 
@@ -225,59 +233,78 @@ def _find_user_function_in_closure(closure: tuple) -> Callable | None:
225
233
 
226
234
 
227
235
  class VerisConfig(BaseModel):
228
- """Configuration for the Veris SDK."""
236
+ """Configuration for the Veris SDK Runner.
237
+
238
+ Attributes:
239
+ include_tools: Optional list of tool names to intercept (only these if provided)
240
+ exclude_tools: Optional list of tool names to NOT intercept (these run normally)
241
+ tool_options: Optional per-tool configuration for mocking behavior
242
+ """
229
243
 
230
244
  include_tools: list[str] | None = None
231
245
  exclude_tools: list[str] | None = None
246
+ tool_options: dict[str, ToolCallOptions] | None = None
232
247
 
233
248
 
234
- def veris_runner(
235
- starting_agent: Any, # noqa: ANN401
236
- input_text: str,
237
- veris_config: VerisConfig | None = None,
238
- **kwargs: Any, # noqa: ANN401
239
- ) -> RunResult: # noqa: ANN401
240
- """Veris-wrapped version of OpenAI agents Runner.run.
241
-
242
- This function wraps the OpenAI agents Runner.run to intercept tool calls
243
- and route them through the Veris SDK's mocking infrastructure. It can be
244
- used as a drop-in replacement for Runner.run with an additional veris_config parameter.
249
+ class Runner(OpenAIRunner):
250
+ """Veris-enhanced Runner that extends OpenAI's Runner with tool interception.
245
251
 
246
- Args:
247
- starting_agent: The OpenAI agent to run
248
- input_text: The input text to process
249
- veris_config: Optional configuration for Veris SDK tool interception
250
- **kwargs: Additional arguments to pass to Runner.run
251
-
252
- Returns:
253
- The result from Runner.run
252
+ This class extends the OpenAI agents Runner to intercept tool calls
253
+ and route them through the Veris SDK's mocking infrastructure.
254
254
 
255
255
  Example:
256
256
  ```python
257
- from veris_ai import veris_runner, VerisConfig
257
+ from veris_ai import Runner, VerisConfig
258
258
  from agents import Agent, FunctionTool
259
259
 
260
260
  # Define your agent with tools
261
261
  agent = Agent(...)
262
262
 
263
- # Use veris_runner instead of Runner.run
264
- result = await veris_runner(agent, "Process this input")
263
+ # Use Veris Runner instead of OpenAI Runner
264
+ result = await Runner.run(agent, "Process this input")
265
265
 
266
- # Or with specific tool configuration
266
+ # Or with configuration
267
267
  config = VerisConfig(include_tools=["calculator", "search"])
268
- result = await veris_runner(agent, "Calculate 2+2", veris_config=config)
268
+ result = await Runner.run(agent, "Calculate 2+2", veris_config=config)
269
269
  ```
270
270
  """
271
271
 
272
- # Extract config values
273
- include_tools = None
274
- exclude_tools = None
275
- if veris_config:
276
- include_tools = veris_config.include_tools
277
- exclude_tools = veris_config.exclude_tools
278
-
279
- # Create the wrapped version of Runner.run with the config
280
- wrapped_run = _wrap(include_tools=include_tools, exclude_tools=exclude_tools)(Runner.run)
281
-
282
- # Execute the wrapped run function
283
- return wrapped_run(starting_agent, input_text, **kwargs)
272
+ @classmethod
273
+ async def run(
274
+ cls,
275
+ starting_agent: Any, # noqa: ANN401
276
+ input: Any, # noqa: ANN401, A002
277
+ veris_config: VerisConfig | None = None,
278
+ **kwargs: Any, # noqa: ANN401
279
+ ) -> RunResult: # noqa: ANN401
280
+ """Run an agent with Veris tool interception.
281
+
282
+ This method overrides the OpenAI Runner.run to apply tool interception
283
+ based on the provided configuration.
284
+
285
+ Args:
286
+ starting_agent: The OpenAI agent to run
287
+ input: The input text/messages to process
288
+ veris_config: Optional configuration for tool interception
289
+ **kwargs: Additional arguments to pass to the base Runner.run
290
+
291
+ Returns:
292
+ The result from the agent execution
293
+ """
294
+ # Use provided config or create default
295
+ config = veris_config or VerisConfig()
296
+
297
+ # Validate configuration
298
+ if config.include_tools and config.exclude_tools:
299
+ msg = "Cannot specify both include_tools and exclude_tools"
300
+ raise ValueError(msg)
301
+
302
+ # Apply the wrapping logic
303
+ wrapped_run = _wrap(
304
+ include_tools=config.include_tools,
305
+ exclude_tools=config.exclude_tools,
306
+ tool_options=config.tool_options or {},
307
+ )(OpenAIRunner.run)
308
+
309
+ # Execute the wrapped run function
310
+ return await wrapped_run(starting_agent, input, **kwargs)
veris_ai/models.py CHANGED
@@ -19,4 +19,4 @@ class ToolCallOptions(BaseModel):
19
19
 
20
20
  response_expectation: ResponseExpectation = ResponseExpectation.AUTO
21
21
  cache_response: bool = False
22
- mode: Literal["tool", "function", "spy"] = "tool"
22
+ mode: Literal["tool", "function"] = "tool"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: veris-ai
3
- Version: 1.8.2
3
+ Version: 1.9.0
4
4
  Summary: A Python package for Veris AI tools
5
5
  Project-URL: Homepage, https://github.com/veris-ai/veris-python-sdk
6
6
  Project-URL: Bug Tracker, https://github.com/veris-ai/veris-python-sdk/issues
@@ -47,7 +47,7 @@ A Python package for Veris AI tools with simulation capabilities and FastAPI MCP
47
47
  ## Quick Reference
48
48
 
49
49
  **Purpose**: Tool mocking, tracing, and FastAPI MCP integration for AI agent development
50
- **Core Components**: [`tool_mock`](#function-mocking) • [`api_client`](src/veris_ai/api_client.py) • [`observability`](#sdk-observability-helpers) • [`fastapi_mcp`](#fastapi-mcp-integration) • [`jaeger_interface`](#jaeger-trace-interface)
50
+ **Core Components**: [`tool_mock`](#function-mocking) • [`api_client`](src/veris_ai/api_client.py) • [`observability`](#sdk-observability-helpers) • [`agents_wrapper`](#openai-agents-integration) • [`fastapi_mcp`](#fastapi-mcp-integration) • [`jaeger_interface`](#jaeger-trace-interface)
51
51
  **Deep Dive**: [`Module Architecture`](src/veris_ai/README.md) • [`Testing Guide`](tests/README.md) • [`Usage Examples`](examples/README.md)
52
52
  **Source of Truth**: Implementation details in [`src/veris_ai/`](src/veris_ai/) source code
53
53
 
@@ -58,13 +58,14 @@ A Python package for Veris AI tools with simulation capabilities and FastAPI MCP
58
58
  uv add veris-ai
59
59
 
60
60
  # With optional extras
61
- uv add "veris-ai[dev,fastapi,instrument]"
61
+ uv add "veris-ai[dev,fastapi,observability,agents]"
62
62
  ```
63
63
 
64
64
  **Installation Profiles**:
65
65
  - `dev`: Development tools (ruff, pytest, mypy)
66
66
  - `fastapi`: FastAPI MCP integration
67
67
  - `observability`: OpenTelemetry tracing
68
+ - `agents`: OpenAI agents integration
68
69
 
69
70
  ## Import Patterns
70
71
 
@@ -75,10 +76,11 @@ uv add "veris-ai[dev,fastapi,instrument]"
75
76
  from veris_ai import veris, JaegerClient
76
77
 
77
78
  # Optional features (require extras)
78
- from veris_ai import init_observability, instrument_fastapi_app # Provided by SDK observability helpers
79
+ from veris_ai import init_observability, instrument_fastapi_app # Requires observability extras
80
+ from veris_ai import Runner, VerisConfig # Requires agents extras
79
81
  ```
80
82
 
81
- **Complete Import Strategies**: See [`examples/README.md`](examples/README.md) for five different import approaches, conditional features, and integration patterns.
83
+ **Complete Import Strategies**: See [`examples/README.md`](examples/README.md) for different import approaches, conditional features, and integration patterns.
82
84
 
83
85
  ## Configuration
84
86
 
@@ -182,6 +184,107 @@ async def get_data() -> dict:
182
184
 
183
185
  **Implementation**: See [`src/veris_ai/tool_mock.py`](src/veris_ai/tool_mock.py) for decorator logic and API integration.
184
186
 
187
+ ## OpenAI Agents Integration
188
+
189
+ **Semantic Tag**: `openai-agents`
190
+
191
+ The SDK provides seamless integration with [OpenAI's agents library](https://github.com/openai/agents) through the `Runner` class, which extends OpenAI's Runner to intercept tool calls and route them through Veris's mocking infrastructure.
192
+
193
+ ### Installation
194
+
195
+ ```bash
196
+ # Install with agents support
197
+ uv add "veris-ai[agents]"
198
+ ```
199
+
200
+ ### Basic Usage
201
+
202
+ ```python
203
+ from veris_ai import veris, Runner, VerisConfig
204
+ from agents import Agent, function_tool
205
+
206
+ # Define your tools
207
+ @function_tool
208
+ def calculator(x: int, y: int, operation: str = "add") -> int:
209
+ """Performs arithmetic operations."""
210
+ # ... implementation ...
211
+
212
+ # Create an agent with tools
213
+ agent = Agent(
214
+ name="Assistant",
215
+ model="gpt-4",
216
+ tools=[calculator],
217
+ instructions="You are a helpful assistant.",
218
+ )
219
+
220
+ # Use Veris Runner instead of OpenAI's Runner
221
+ result = await Runner.run(agent, "Calculate 10 + 5")
222
+
223
+ # Or with configuration
224
+ config = VerisConfig(include_tools=["calculator"])
225
+ result = await Runner.run(agent, "Calculate 10 + 5", veris_config=config)
226
+ ```
227
+
228
+ ### Selective Tool Interception
229
+
230
+ Control which tools are intercepted using VerisConfig:
231
+
232
+ ```python
233
+ from veris_ai import Runner, VerisConfig
234
+
235
+ # Only intercept specific tools
236
+ config = VerisConfig(include_tools=["calculator", "search_web"])
237
+ result = await Runner.run(agent, "Process this", veris_config=config)
238
+
239
+ # Or exclude specific tools from interception
240
+ config = VerisConfig(exclude_tools=["get_weather"])
241
+ result = await Runner.run(agent, "Check weather", veris_config=config)
242
+ ```
243
+
244
+ ### Advanced Tool Configuration
245
+
246
+ Fine-tune individual tool behavior using `ToolCallOptions`:
247
+
248
+ ```python
249
+ from veris_ai import Runner, VerisConfig, ResponseExpectation, ToolCallOptions
250
+
251
+ # Configure specific tool behaviors
252
+ config = VerisConfig(
253
+ tool_options={
254
+ "calculator": ToolCallOptions(
255
+ response_expectation=ResponseExpectation.REQUIRED, # Always expect response
256
+ cache_response=True, # Cache responses for identical calls
257
+ mode="tool" # Use tool mode (default)
258
+ ),
259
+ "search_web": ToolCallOptions(
260
+ response_expectation=ResponseExpectation.NONE, # Don't wait for response
261
+ cache_response=False,
262
+ mode="spy" # Log calls but execute normally
263
+ )
264
+ }
265
+ )
266
+
267
+ result = await Runner.run(agent, "Calculate and search", veris_config=config)
268
+ ```
269
+
270
+ **ToolCallOptions Parameters**:
271
+ - `response_expectation`: Control response behavior
272
+ - `AUTO` (default): Automatically determine based on context
273
+ - `REQUIRED`: Always wait for mock response
274
+ - `NONE`: Don't wait for response
275
+ - `cache_response`: Cache responses for identical tool calls
276
+ - `mode`: Tool execution mode
277
+ - `"tool"` (default): Standard tool execution
278
+ - `"function"`: Function mode
279
+
280
+ **Key Features**:
281
+ - **Drop-in replacement**: Use `Runner` from veris_ai instead of OpenAI's Runner
282
+ - **Extends OpenAI Runner**: Inherits all functionality while adding Veris capabilities
283
+ - **Automatic session management**: Integrates with Veris session IDs
284
+ - **Selective mocking**: Include or exclude specific tools from interception
285
+
286
+ **Implementation**: See [`src/veris_ai/agents_wrapper.py`](src/veris_ai/agents_wrapper.py) for the integration logic and [`examples/openai_agents_example.py`](examples/openai_agents_example.py) for complete examples.
287
+
185
288
  ## FastAPI MCP Integration
186
289
 
187
290
  **Semantic Tag**: `fastapi-mcp`
@@ -254,7 +357,7 @@ pytest --cov=veris_ai # Test with coverage
254
357
 
255
358
  **Semantic Tag**: `module-architecture`
256
359
 
257
- **Core Modules**: `tool_mock` (mocking), `api_client` (centralized API), `jaeger_interface` (trace queries), `utils` (schema conversion)
360
+ **Core Modules**: `tool_mock` (mocking), `api_client` (centralized API), `agents_wrapper` (OpenAI agents integration), `jaeger_interface` (trace queries), `utils` (schema conversion)
258
361
 
259
362
  **Complete Architecture**: See [`src/veris_ai/README.md`](src/veris_ai/README.md) for module overview, implementation flows, and configuration details.
260
363
 
@@ -1,9 +1,9 @@
1
1
  veris_ai/README.md,sha256=0EC-yWB8FtqAhtcE5Q204bS1JWJPIvfpp1bPDo6iwwc,3601
2
- veris_ai/__init__.py,sha256=mFEF2pHXOAXoXuBh9IOQgqpKGvzLOsy8b0vUpMRJggU,2260
3
- veris_ai/agents_wrapper.py,sha256=LmxPkOg3KLICgTrl0Bouy7enhyO4tF6_evq2cb8I_ig,10718
2
+ veris_ai/__init__.py,sha256=enl_gEa6BQAjWvzCtsn_hFVJVVlJZ_dMsLL--E5W3nU,1907
3
+ veris_ai/agents_wrapper.py,sha256=L4llszfyZkG4Xjo8OTeVfm-IIdESAcW51ukxceKc88U,11907
4
4
  veris_ai/api_client.py,sha256=Gu_ovqaW-hZ6yPee2GVconMeg_xOxlt7IKu0HJQNiD0,2192
5
5
  veris_ai/logging.py,sha256=ENduOHnc5UmzciTDZDJCZqUOXb5We-bdtwN9f9Qqwl0,1360
6
- veris_ai/models.py,sha256=TiQJuME2pGDE6EY5J8TYKNSeajaN2Xk9ISsLoIwgtgU,502
6
+ veris_ai/models.py,sha256=xKeheSJQle2tBeJG1DsGJzMDwv24p5jECjX6RAa39n4,495
7
7
  veris_ai/observability.py,sha256=fDtWeUexfzaIQArE5YbWsja8Y-bcE_h0dXQWYbXbupY,4929
8
8
  veris_ai/tool_mock.py,sha256=L2p6Yg8S98floahDTrf6cnmDqC6Dq3YKA7Q6RRvv7BQ,10253
9
9
  veris_ai/utils.py,sha256=Ud4k2jKAJ6-nqSsFXIJWYrOmPGmvl5RSp36cQtgnMpg,9781
@@ -11,7 +11,7 @@ veris_ai/jaeger_interface/README.md,sha256=kd9rKcE5xf3EyNaiHu0tjn-0oES9sfaK6Ih-O
11
11
  veris_ai/jaeger_interface/__init__.py,sha256=KD7NSiMYRG_2uF6dOLKkGG5lNQe4K9ptEwucwMT4_aw,1128
12
12
  veris_ai/jaeger_interface/client.py,sha256=yJrh86wRR0Dk3Gq12DId99WogcMIVbL0QQFqVSevvlE,8772
13
13
  veris_ai/jaeger_interface/models.py,sha256=e64VV6IvOEFuzRUgvDAMQFyOZMRb56I-PUPZLBZ3rX0,1864
14
- veris_ai-1.8.2.dist-info/METADATA,sha256=Qw1UFcpv4cc7kpozLsUds6R8p5inAadVz0SSnYqwBQs,9924
15
- veris_ai-1.8.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- veris_ai-1.8.2.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
17
- veris_ai-1.8.2.dist-info/RECORD,,
14
+ veris_ai-1.9.0.dist-info/METADATA,sha256=8c5TObTTfXNUiV0uTiTUu1sAZs7VOcrki1Q-00sGn_8,13495
15
+ veris_ai-1.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ veris_ai-1.9.0.dist-info/licenses/LICENSE,sha256=2g4i20atAgtD5einaKzhQrIB-JrPhyQgD3bC0wkHcCI,1065
17
+ veris_ai-1.9.0.dist-info/RECORD,,