@macaw-ai/client 0.0.0-stage → 0.9.11

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.
Files changed (142) hide show
  1. package/LICENSE.md +339 -0
  2. package/bin/install.js +422 -0
  3. package/package.json +37 -4
  4. package/payload/README.md +56 -0
  5. package/payload/secureAI/LICENSE +190 -0
  6. package/payload/secureAI/NOTICE +5 -0
  7. package/payload/secureAI/demos/policy-controls/1_uncontrolled.py +139 -0
  8. package/payload/secureAI/demos/policy-controls/2_with_macaw.py +139 -0
  9. package/payload/secureAI/demos/policy-controls/3_with_user_policies.py +162 -0
  10. package/payload/secureAI/demos/policy-controls/credentials.txt +12 -0
  11. package/payload/secureAI/demos/policy-controls/malicious_report.txt +21 -0
  12. package/payload/secureAI/demos/policy-controls/sales_report.txt +20 -0
  13. package/payload/secureAI/demos/tutorial-1-rbac/README.md +143 -0
  14. package/payload/secureAI/demos/tutorial-1-rbac/app.py +147 -0
  15. package/payload/secureAI/demos/tutorial-1-rbac/authprompts_demo.py +306 -0
  16. package/payload/secureAI/demos/tutorial-1-rbac/config/claims-config.yaml +152 -0
  17. package/payload/secureAI/demos/tutorial-1-rbac/demo_secureopenai_with_policies.py +150 -0
  18. package/payload/secureAI/demos/tutorial-1-rbac/policies/bu_Analytics.json +8 -0
  19. package/payload/secureAI/demos/tutorial-1-rbac/policies/company_FinTech_Corp.json +70 -0
  20. package/payload/secureAI/demos/tutorial-1-rbac/policies/llm-base.json +69 -0
  21. package/payload/secureAI/demos/tutorial-1-rbac/policies/team_Reporting.json +8 -0
  22. package/payload/secureAI/demos/tutorial-1-rbac/policies/user_alice.json +32 -0
  23. package/payload/secureAI/demos/tutorial-1-rbac/policies/user_bob.json +28 -0
  24. package/payload/secureAI/demos/tutorial-1-rbac/policies/user_carol.json +34 -0
  25. package/payload/secureAI/demos/tutorial-1-rbac/requirements.txt +6 -0
  26. package/payload/secureAI/demos/tutorial-1-rbac/setup/auth0_complete_setup.sh +392 -0
  27. package/payload/secureAI/demos/tutorial-1-rbac/setup/keycloak_complete_setup.sh +320 -0
  28. package/payload/secureAI/demos/tutorial-2-intent/Policies/alation-remote-proxy.json +155 -0
  29. package/payload/secureAI/demos/tutorial-2-intent/Policies/bu.json +22 -0
  30. package/payload/secureAI/demos/tutorial-2-intent/Policies/company.json +17 -0
  31. package/payload/secureAI/demos/tutorial-2-intent/Policies/user_alice.json +48 -0
  32. package/payload/secureAI/demos/tutorial-2-intent/Policies/user_bob.json +83 -0
  33. package/payload/secureAI/demos/tutorial-2-intent/README.md +213 -0
  34. package/payload/secureAI/demos/tutorial-2-intent/script.py +188 -0
  35. package/payload/secureAI/demos/tutorial-2-intent/setup/alation_verifier.py +177 -0
  36. package/payload/secureAI/demos/tutorial-2-intent/setup/get_alation_user_token.py +180 -0
  37. package/payload/secureAI/examples/README.md +244 -0
  38. package/payload/secureAI/examples/anthropic/anthropic_1a_dropin_simple.py +103 -0
  39. package/payload/secureAI/examples/anthropic/anthropic_1b_multiuser_bind.py +190 -0
  40. package/payload/secureAI/examples/anthropic/anthropic_1b_multiuser_bind_streaming.py +190 -0
  41. package/payload/secureAI/examples/anthropic/anthropic_1c_a2a_invoke.py +156 -0
  42. package/payload/secureAI/examples/attestations/1a_trade_alice.py +215 -0
  43. package/payload/secureAI/examples/attestations/1a_trade_bob.py +164 -0
  44. package/payload/secureAI/examples/attestations/1b_grant_admin.py +170 -0
  45. package/payload/secureAI/examples/attestations/1b_grant_researcher.py +231 -0
  46. package/payload/secureAI/examples/attestations/README.md +128 -0
  47. package/payload/secureAI/examples/langchain/langchain_1a_dropin_simple.py +199 -0
  48. package/payload/secureAI/examples/langchain/langchain_1b_multiuser.py +262 -0
  49. package/payload/secureAI/examples/langchain/langchain_1c_orchestration.py +332 -0
  50. package/payload/secureAI/examples/langchain/langchain_1d_llm_openai.py +130 -0
  51. package/payload/secureAI/examples/langchain/langchain_1e_llm_anthropic.py +130 -0
  52. package/payload/secureAI/examples/langchain/langchain_1f_memory.py +214 -0
  53. package/payload/secureAI/examples/litellm/litellm_1a_dropin_simple.py +131 -0
  54. package/payload/secureAI/examples/mcp/1a_simple_invocation.py +115 -0
  55. package/payload/secureAI/examples/mcp/1b_discovery_and_resources.py +142 -0
  56. package/payload/secureAI/examples/mcp/1c_logging_client.py +100 -0
  57. package/payload/secureAI/examples/mcp/1d_progress_client.py +100 -0
  58. package/payload/secureAI/examples/mcp/1e_sampling_client.py +150 -0
  59. package/payload/secureAI/examples/mcp/1e_sampling_server.py +90 -0
  60. package/payload/secureAI/examples/mcp/1f_elicitation_client.py +127 -0
  61. package/payload/secureAI/examples/mcp/1f_elicitation_server.py +73 -0
  62. package/payload/secureAI/examples/mcp/1g_roots_client.py +122 -0
  63. package/payload/secureAI/examples/mcp/1g_roots_server.py +85 -0
  64. package/payload/secureAI/examples/mcp/2a_proxy_snowflake.py +212 -0
  65. package/payload/secureAI/examples/mcp/2b_proxy_databricks.py +299 -0
  66. package/payload/secureAI/examples/mcp/2c_proxy_stdio_fetch.py +91 -0
  67. package/payload/secureAI/examples/mcp/2d_proxy_stdio_salesforce.py +119 -0
  68. package/payload/secureAI/examples/mcp/2e_proxy_multiuser.py +136 -0
  69. package/payload/secureAI/examples/mcp/2f_proxy_stdio_databricks.py +144 -0
  70. package/payload/secureAI/examples/mcp/3a_native_mcp_client.py +104 -0
  71. package/payload/secureAI/examples/mcp/3b_native_mcp_proxy.py +114 -0
  72. package/payload/secureAI/examples/mcp/3c_native_mcp_sampling.py +180 -0
  73. package/payload/secureAI/examples/mcp/3d_native_mcp_2026.py +135 -0
  74. package/payload/secureAI/examples/mcp/securemcp_calculator.py +248 -0
  75. package/payload/secureAI/examples/mcp/securemcp_server.py +75 -0
  76. package/payload/secureAI/examples/openai/openai_1a_dropin_simple.py +102 -0
  77. package/payload/secureAI/examples/openai/openai_1b_multiuser_bind.py +193 -0
  78. package/payload/secureAI/examples/openai/openai_1b_multiuser_bind_streaming.py +199 -0
  79. package/payload/secureAI/examples/openai/openai_1c_a2a_invoke.py +156 -0
  80. package/payload/secureAI/examples/openai/openai_1d_invocation_patterns.py +337 -0
  81. package/payload/secureAI/examples/phishing-resistance/1a_login_alice.py +180 -0
  82. package/payload/secureAI/examples/phishing-resistance/1b_trade_alice.py +241 -0
  83. package/payload/secureAI/examples/phishing-resistance/1b_trade_bob.py +164 -0
  84. package/payload/secureAI/examples/phishing-resistance/README.md +124 -0
  85. package/payload/secureAI/examples/phishing-resistance/get_token.py +114 -0
  86. package/payload/secureAI/examples/pydantic_ai/README.md +88 -0
  87. package/payload/secureAI/examples/pydantic_ai/policies/app_pydantic-agent.json +10 -0
  88. package/payload/secureAI/examples/pydantic_ai/pydanticai_1a_dropin_simple.py +90 -0
  89. package/payload/secureAI/examples/pydantic_ai/pydanticai_1b_model_routing.py +85 -0
  90. package/payload/secureAI/examples/pydantic_ai/pydanticai_1c_native_tools.py +83 -0
  91. package/payload/secureAI/examples/pydantic_ai/pydanticai_1d_multiuser_bind.py +104 -0
  92. package/payload/secureAI/examples/pydantic_ai/pydanticai_1e_mcp_compose.py +92 -0
  93. package/payload/secureAI/macaw_adapters/__init__.py +55 -0
  94. package/payload/secureAI/macaw_adapters/anthropic/REFERENCE.md +374 -0
  95. package/payload/secureAI/macaw_adapters/anthropic/__init__.py +22 -0
  96. package/payload/secureAI/macaw_adapters/anthropic/secure_anthropic.py +792 -0
  97. package/payload/secureAI/macaw_adapters/anthropic_ext_tools/__init__.py +25 -0
  98. package/payload/secureAI/macaw_adapters/anthropic_ext_tools/secure_anthropic.py +840 -0
  99. package/payload/secureAI/macaw_adapters/langchain/REFERENCE.md +234 -0
  100. package/payload/secureAI/macaw_adapters/langchain/__init__.py +100 -0
  101. package/payload/secureAI/macaw_adapters/langchain/_utils.py +83 -0
  102. package/payload/secureAI/macaw_adapters/langchain/agents.py +296 -0
  103. package/payload/secureAI/macaw_adapters/langchain/anthropic.py +456 -0
  104. package/payload/secureAI/macaw_adapters/langchain/callbacks.py +306 -0
  105. package/payload/secureAI/macaw_adapters/langchain/memory.py +352 -0
  106. package/payload/secureAI/macaw_adapters/langchain/openai.py +410 -0
  107. package/payload/secureAI/macaw_adapters/langchain/tools.py +174 -0
  108. package/payload/secureAI/macaw_adapters/litellm/README.md +216 -0
  109. package/payload/secureAI/macaw_adapters/litellm/__init__.py +143 -0
  110. package/payload/secureAI/macaw_adapters/litellm/secure_litellm.py +686 -0
  111. package/payload/secureAI/macaw_adapters/mcp/REFERENCE.md +460 -0
  112. package/payload/secureAI/macaw_adapters/mcp/__init__.py +65 -0
  113. package/payload/secureAI/macaw_adapters/mcp/_endpoint.py +193 -0
  114. package/payload/secureAI/macaw_adapters/mcp/_endpoint2.py +225 -0
  115. package/payload/secureAI/macaw_adapters/mcp/_serve.py +25 -0
  116. package/payload/secureAI/macaw_adapters/mcp/client.py +721 -0
  117. package/payload/secureAI/macaw_adapters/mcp/decorators.py +228 -0
  118. package/payload/secureAI/macaw_adapters/mcp/fastmcp_compat.py +353 -0
  119. package/payload/secureAI/macaw_adapters/mcp/mcp.py +785 -0
  120. package/payload/secureAI/macaw_adapters/mcp/proxy.py +626 -0
  121. package/payload/secureAI/macaw_adapters/mcp/server.py +317 -0
  122. package/payload/secureAI/macaw_adapters/mcp/subscriptions.py +450 -0
  123. package/payload/secureAI/macaw_adapters/openai/REFERENCE.md +368 -0
  124. package/payload/secureAI/macaw_adapters/openai/__init__.py +22 -0
  125. package/payload/secureAI/macaw_adapters/openai/secure_openai.py +833 -0
  126. package/payload/secureAI/macaw_adapters/openai_ext_tools/REFERENCE.md +368 -0
  127. package/payload/secureAI/macaw_adapters/openai_ext_tools/__init__.py +25 -0
  128. package/payload/secureAI/macaw_adapters/openai_ext_tools/secure_openai.py +876 -0
  129. package/payload/secureAI/macaw_adapters/pydantic_ai/__init__.py +36 -0
  130. package/payload/secureAI/macaw_adapters/pydantic_ai/_core.py +257 -0
  131. package/payload/secureAI/macaw_adapters/pydantic_ai/agent.py +218 -0
  132. package/payload/secureAI/macaw_adapters/pydantic_ai/model.py +99 -0
  133. package/payload/secureAI/macaw_adapters/pydantic_ai/toolset.py +86 -0
  134. package/payload/secureAI/test_harness_quick.py +296 -0
  135. package/wheels/macaw_adapters-0.9.10.1-py3-none-any.whl +0 -0
  136. package/wheels/macaw_client-0.9.10.1-cp312-cp312-macosx_11_0_arm64.whl +0 -0
  137. package/wheels/macaw_client-0.9.10.1-cp312-cp312-manylinux_2_17_x86_64.whl +0 -0
  138. package/wheels/macaw_client-0.9.10.1-cp314-cp314-macosx_11_0_arm64.whl +0 -0
  139. package/wheels/macaw_client-0.9.10.1-cp314-cp314-manylinux_2_17_x86_64.whl +0 -0
  140. package/wheels/macaw_client-0.9.10.1-cp314-cp314-win_amd64.whl +0 -0
  141. package/wheels/macaw_client-0.9.10.1-cp39-cp39-macosx_11_0_arm64.whl +0 -0
  142. package/README.md +0 -3
@@ -0,0 +1,368 @@
1
+ # SecureOpenAI Reference
2
+
3
+ Drop-in replacement for OpenAI client with MACAW security. Supports three usage paths for different scenarios.
4
+
5
+ ## Installation
6
+
7
+ ```python
8
+ from macaw_adapters.openai import SecureOpenAI
9
+ ```
10
+
11
+ Install the package:
12
+ ```bash
13
+ pip install -e /path/to/secureAI
14
+ ```
15
+
16
+ ---
17
+
18
+ ## When to Use Each Path
19
+
20
+ | Scenario | Path | Example |
21
+ |----------|------|---------|
22
+ | Simple app, no user distinction | Direct on service | `client.chat.completions.create()` |
23
+ | Multi-user, per-user policies | bind_to_user | `service.bind_to_user(user_client)` |
24
+ | A2A communication, explicit control | invoke_tool | `user.invoke_tool("tool:xxx/generate", ...)` |
25
+ | CLI tool, single operator | Direct on service | `client.chat.completions.create()` |
26
+ | SaaS with user accounts | bind_to_user | Different users = different permissions |
27
+
28
+ ### Why bind_to_user?
29
+
30
+ Without `bind_to_user`, everyone uses the **service's identity**. With `bind_to_user`, each user's **JWT identity flows through** for policy evaluation.
31
+
32
+ This enables scenarios like:
33
+ - Alice: GPT-3.5 only, max 500 tokens
34
+ - Bob: GPT-3.5/4, max 2000 tokens
35
+
36
+ Same service, different permissions based on WHO is calling.
37
+
38
+ ---
39
+
40
+ ## Path 1: Direct on Service (Simplest)
41
+
42
+ ```python
43
+ from macaw_adapters.openai import SecureOpenAI
44
+
45
+ # Just like using regular OpenAI client
46
+ client = SecureOpenAI(
47
+ app_name="my-app",
48
+ intent_policy={"purpose": "financial analysis"}
49
+ )
50
+
51
+ # Same API as OpenAI
52
+ response = client.chat.completions.create(
53
+ model="gpt-4",
54
+ max_tokens=500,
55
+ messages=[{"role": "user", "content": "What is compound interest?"}]
56
+ )
57
+
58
+ print(response.choices[0].message.content)
59
+ ```
60
+
61
+ **Use when**: Single app, no user distinction, app-level policies.
62
+
63
+ ---
64
+
65
+ ## Path 2: bind_to_user (Multi-user)
66
+
67
+ ```python
68
+ from macaw_adapters.openai import SecureOpenAI
69
+ from macaw_client import MACAWClient, RemoteIdentityProvider
70
+
71
+ # 1. Create SINGLE service (shared across all users)
72
+ service = SecureOpenAI(app_name="financial-service")
73
+
74
+ # 2. User login -> JWT -> MACAWClient
75
+ jwt_token, _ = RemoteIdentityProvider().login("alice", "Alice123!")
76
+ user = MACAWClient(
77
+ user_name="alice",
78
+ iam_token=jwt_token,
79
+ agent_type="user",
80
+ app_name="financial-app"
81
+ )
82
+ user.register()
83
+
84
+ # 3. Bind user to service
85
+ user_openai = service.bind_to_user(user)
86
+
87
+ # 4. Same API, user's identity flows through for policy evaluation
88
+ response = user_openai.chat.completions.create(
89
+ model="gpt-3.5-turbo",
90
+ messages=[{"role": "user", "content": "Hello"}]
91
+ )
92
+
93
+ # 5. Cleanup when user session ends
94
+ user_openai.unbind()
95
+ ```
96
+
97
+ **Use when**: SaaS app, different users need different permissions.
98
+
99
+ ---
100
+
101
+ ## Path 3: invoke_tool (A2A)
102
+
103
+ ```python
104
+ from macaw_adapters.openai import SecureOpenAI
105
+ from macaw_client import MACAWClient, RemoteIdentityProvider
106
+
107
+ # 1. Create OpenAI service
108
+ service = SecureOpenAI(app_name="openai-service")
109
+
110
+ # 2. Create user agent
111
+ jwt_token, _ = RemoteIdentityProvider().login("alice", "Alice123!")
112
+ user = MACAWClient(
113
+ user_name="alice",
114
+ iam_token=jwt_token,
115
+ agent_type="user",
116
+ app_name="my-agent"
117
+ )
118
+ user.register()
119
+
120
+ # 3. Explicit invoke_tool - you control everything
121
+ result = user.invoke_tool(
122
+ tool_name="tool:openai-service/generate", # MAPL tool name
123
+ parameters={
124
+ "model": "gpt-3.5-turbo",
125
+ "max_tokens": 500,
126
+ "messages": [{"role": "user", "content": "What is compound interest?"}]
127
+ },
128
+ target_agent=service.server_id # Explicit routing
129
+ )
130
+
131
+ # Result is raw dict
132
+ content = result["choices"][0]["message"]["content"]
133
+ ```
134
+
135
+ **Use when**: Building agent systems, need explicit control, cross-service communication.
136
+
137
+ ---
138
+
139
+ ## SecureOpenAI Class
140
+
141
+ ```python
142
+ client = SecureOpenAI(
143
+ api_key="sk-...", # Optional: uses OPENAI_API_KEY env var
144
+ app_name="my-app", # Application name for MACAW registration
145
+ intent_policy={...}, # Application-defined security policy (MAPL format)
146
+ jwt_token="...", # Optional: creates user-mode client
147
+ user_name="alice" # Optional: user name for user mode
148
+ )
149
+ ```
150
+
151
+ ### Constructor Parameters
152
+
153
+ | Parameter | Type | Default | Description |
154
+ |-----------|------|---------|-------------|
155
+ | `api_key` | str | env var | OpenAI API key |
156
+ | `app_name` | str | `"secure-openai-app"` | Application name for MACAW |
157
+ | `intent_policy` | dict | `{}` | Security policy (MAPL format) |
158
+ | `jwt_token` | str | None | JWT token for user mode |
159
+ | `user_name` | str | None | User name for user mode |
160
+
161
+ ### Properties
162
+
163
+ | Property | Type | Description |
164
+ |----------|------|-------------|
165
+ | `client.server_id` | str | Agent ID after registration |
166
+ | `client.macaw_client` | MACAWClient | MACAW client instance |
167
+ | `client.openai_client` | OpenAI | Underlying OpenAI client |
168
+ | `client._mode` | str | "service" or "user" |
169
+
170
+ ### Methods
171
+
172
+ #### bind_to_user(user_client) -> BoundSecureOpenAI
173
+
174
+ Bind service to a user's MACAW client for per-user identity.
175
+
176
+ ```python
177
+ user_openai = service.bind_to_user(user_client)
178
+ ```
179
+
180
+ Only valid in service mode. Returns `BoundSecureOpenAI` wrapper.
181
+
182
+ #### register_tool(name, handler) -> SecureOpenAI
183
+
184
+ Register a tool that OpenAI can call.
185
+
186
+ ```python
187
+ client.register_tool("get_weather", get_weather_fn)
188
+ ```
189
+
190
+ ---
191
+
192
+ ## BoundSecureOpenAI Class
193
+
194
+ Per-user wrapper created via `bind_to_user()`.
195
+
196
+ ```python
197
+ user_openai = service.bind_to_user(user_client)
198
+
199
+ # Same API as SecureOpenAI
200
+ response = user_openai.chat.completions.create(...)
201
+
202
+ # Check binding status
203
+ if user_openai.is_bound:
204
+ ...
205
+
206
+ # Cleanup
207
+ user_openai.unbind()
208
+ ```
209
+
210
+ ### Properties
211
+
212
+ | Property | Type | Description |
213
+ |----------|------|-------------|
214
+ | `is_bound` | bool | Whether wrapper is still bound |
215
+ | `service` | SecureOpenAI | The bound service (raises if unbound) |
216
+ | `user_client` | MACAWClient | The bound user client (raises if unbound) |
217
+
218
+ ### Methods
219
+
220
+ #### unbind()
221
+
222
+ Invalidate this binding. All future calls will raise `RuntimeError`.
223
+
224
+ ---
225
+
226
+ ## API Surface
227
+
228
+ SecureOpenAI mirrors the OpenAI API structure:
229
+
230
+ ```python
231
+ # Chat completions
232
+ response = client.chat.completions.create(
233
+ model="gpt-4",
234
+ messages=[{"role": "user", "content": "..."}],
235
+ tools=[...], # Optional: auto-discovered
236
+ tool_choice="auto"
237
+ )
238
+
239
+ # Text completions
240
+ response = client.completions.create(
241
+ model="gpt-3.5-turbo-instruct",
242
+ prompt="..."
243
+ )
244
+
245
+ # Embeddings
246
+ response = client.embeddings.create(
247
+ model="text-embedding-ada-002",
248
+ input="..."
249
+ )
250
+ ```
251
+
252
+ ---
253
+
254
+ ## MAPL Tool Names
255
+
256
+ SecureOpenAI uses MAPL-compliant tool names:
257
+
258
+ | Operation | Tool Name |
259
+ |-----------|-----------|
260
+ | Chat completions | `tool:{app_name}/generate` |
261
+ | Text completions | `tool:{app_name}/complete` |
262
+ | Embeddings | `tool:{app_name}/embed` |
263
+
264
+ Example: If `app_name="openai-service"`, the generate tool is `tool:openai-service/generate`.
265
+
266
+ ---
267
+
268
+ ## Tool Auto-Discovery
269
+
270
+ SecureOpenAI automatically discovers tool implementations from the caller's scope:
271
+
272
+ ```python
273
+ # Define tools in your code
274
+ def get_weather(location: str) -> str:
275
+ return f"Weather in {location}: Sunny, 72F"
276
+
277
+ # Define tool schemas for OpenAI
278
+ tools = [
279
+ {
280
+ "type": "function",
281
+ "function": {
282
+ "name": "get_weather", # Must match function name
283
+ "description": "Get weather for a location",
284
+ "parameters": {
285
+ "type": "object",
286
+ "properties": {"location": {"type": "string"}},
287
+ "required": ["location"]
288
+ }
289
+ }
290
+ }
291
+ ]
292
+
293
+ # Tools are auto-discovered and routed through MACAW PEP
294
+ response = client.chat.completions.create(
295
+ model="gpt-4",
296
+ messages=[{"role": "user", "content": "What's the weather in Paris?"}],
297
+ tools=tools
298
+ )
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Intent Policy Format (MAPL)
304
+
305
+ ```python
306
+ intent_policy = {
307
+ # Deny access to sensitive resources
308
+ "denied_resources": ["*password*", "*credential*", "*secret*"],
309
+
310
+ # Allow specific resources
311
+ "resources": ["tool:get_weather", "tool:search_files"],
312
+
313
+ # Parameter constraints
314
+ "constraints": {
315
+ "parameters": {
316
+ "tool:search_files": {
317
+ "path": ["*public*", "*reports*"]
318
+ }
319
+ },
320
+ "denied_parameters": {
321
+ "tool:*": {
322
+ "query": ["*password*"]
323
+ }
324
+ }
325
+ },
326
+
327
+ # Application metadata
328
+ "purpose": "weather and file search app"
329
+ }
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Authenticated Prompts
335
+
336
+ SecureOpenAI supports authenticated prompts for cryptographic proof of prompt origin:
337
+
338
+ ```python
339
+ # Tools declare which parameters are prompts
340
+ self.tools = {
341
+ f"tool:{self.app_name}/generate": {
342
+ "handler": self._handle_generate,
343
+ "prompts": ["messages"] # messages param is authenticated
344
+ }
345
+ }
346
+ ```
347
+
348
+ Authenticated prompts are auto-created when `agent.authenticate_prompts` is enabled.
349
+
350
+ ---
351
+
352
+ ## Migration from OpenAI
353
+
354
+ ```python
355
+ # Before
356
+ from openai import OpenAI
357
+ client = OpenAI()
358
+
359
+ # After (drop-in replacement)
360
+ from macaw_adapters.openai import SecureOpenAI
361
+ client = SecureOpenAI(
362
+ app_name="my-app",
363
+ intent_policy={"denied_resources": ["*sensitive*"]}
364
+ )
365
+
366
+ # Same API - no other code changes needed
367
+ response = client.chat.completions.create(...)
368
+ ```
@@ -0,0 +1,25 @@
1
+ """
2
+ MACAW OpenAI Adapter with Explicit Tools - Enhanced observability version.
3
+
4
+ This version uses a two-client architecture:
5
+ - macaw_client: Primary, owns LLM operations (externally reachable)
6
+ - _tools_client: Internal, owns user tools (not externally reachable)
7
+
8
+ Usage:
9
+ # Standard version
10
+ from macaw_adapters.openai import SecureOpenAI
11
+
12
+ # Explicit tools version (this module)
13
+ from macaw_adapters.openai_ext_tools import SecureOpenAI
14
+ client = SecureOpenAI()
15
+
16
+ Features:
17
+ - Drop-in replacement for OpenAI client
18
+ - Two-client architecture for explicit tool observability
19
+ - Tools isolated on internal client
20
+ - Clear trace flow: LLM → Tools
21
+ """
22
+
23
+ from macaw_adapters.openai_ext_tools.secure_openai import SecureOpenAI
24
+
25
+ __all__ = ["SecureOpenAI"]