deepintshield 2.3.0__tar.gz → 2.4.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.
Files changed (83) hide show
  1. {deepintshield-2.3.0/src/deepintshield.egg-info → deepintshield-2.4.0}/PKG-INFO +33 -33
  2. {deepintshield-2.3.0 → deepintshield-2.4.0}/README.md +32 -32
  3. {deepintshield-2.3.0 → deepintshield-2.4.0}/pyproject.toml +1 -1
  4. deepintshield-2.4.0/src/deepintshield/version.py +1 -0
  5. {deepintshield-2.3.0 → deepintshield-2.4.0/src/deepintshield.egg-info}/PKG-INFO +33 -33
  6. deepintshield-2.3.0/src/deepintshield/version.py +0 -1
  7. {deepintshield-2.3.0 → deepintshield-2.4.0}/LICENSE +0 -0
  8. {deepintshield-2.3.0 → deepintshield-2.4.0}/setup.cfg +0 -0
  9. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/__init__.py +0 -0
  10. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/_gemini_cache.py +0 -0
  11. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/_prompt_cache.py +0 -0
  12. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agent.py +0 -0
  13. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/__init__.py +0 -0
  14. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/__init__.py +0 -0
  15. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/base.py +0 -0
  16. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/entra.py +0 -0
  17. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/oidc.py +0 -0
  18. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/credentials/zeroid.py +0 -0
  19. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/decorators.py +0 -0
  20. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/enforcement.py +0 -0
  21. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/engine.py +0 -0
  22. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/errors.py +0 -0
  23. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/gate.py +0 -0
  24. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/__init__.py +0 -0
  25. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/_common.py +0 -0
  26. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/autogen.py +0 -0
  27. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/crewai.py +0 -0
  28. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/langchain.py +0 -0
  29. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/langgraph.py +0 -0
  30. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/litellm.py +0 -0
  31. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/llamaindex.py +0 -0
  32. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/openai_agents.py +0 -0
  33. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/integrations/pydanticai.py +0 -0
  34. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/manifest.py +0 -0
  35. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/obligations.py +0 -0
  36. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/surface.py +0 -0
  37. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/agentic/types.py +0 -0
  38. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/client.py +0 -0
  39. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/config.py +0 -0
  40. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/errors.py +0 -0
  41. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/__init__.py +0 -0
  42. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/autogen.py +0 -0
  43. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/crewai.py +0 -0
  44. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/langgraph.py +0 -0
  45. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/llamaindex.py +0 -0
  46. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/openai_agents.py +0 -0
  47. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/frameworks/pydanticai.py +0 -0
  48. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/__init__.py +0 -0
  49. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/__init__.py +0 -0
  50. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/anthropic.py +0 -0
  51. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/langchain.py +0 -0
  52. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/adapters/openai.py +0 -0
  53. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/client.py +0 -0
  54. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/mcp/tool.py +0 -0
  55. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/__init__.py +0 -0
  56. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/anthropic.py +0 -0
  57. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/bedrock.py +0 -0
  58. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/genai.py +0 -0
  59. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/langchain.py +0 -0
  60. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/langgraph.py +0 -0
  61. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/litellm.py +0 -0
  62. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/openai.py +0 -0
  63. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/providers/pydanticai.py +0 -0
  64. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/rag.py +0 -0
  65. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/transport.py +0 -0
  66. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield/types.py +0 -0
  67. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/SOURCES.txt +0 -0
  68. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/dependency_links.txt +0 -0
  69. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/requires.txt +0 -0
  70. {deepintshield-2.3.0 → deepintshield-2.4.0}/src/deepintshield.egg-info/top_level.txt +0 -0
  71. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_agent.py +0 -0
  72. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_agentic.py +0 -0
  73. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_agentic_langchain.py +0 -0
  74. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_client.py +0 -0
  75. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_config.py +0 -0
  76. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_errors.py +0 -0
  77. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_gemini_cache.py +0 -0
  78. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_prompt_cache.py +0 -0
  79. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_providers.py +0 -0
  80. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_rag.py +0 -0
  81. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_rag_guard.py +0 -0
  82. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_transport.py +0 -0
  83. {deepintshield-2.3.0 → deepintshield-2.4.0}/tests/test_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepintshield
3
- Version: 2.3.0
3
+ Version: 2.4.0
4
4
  Summary: Unified Python SDK for routing chat, RAG, agentic tool-gating, identity, and MCP traffic through DeepintShield — drop-in across the top agentic frameworks.
5
5
  Author: DeepintShield
6
6
  License: Apache-2.0
@@ -71,7 +71,7 @@ Dynamic: license-file
71
71
 
72
72
  # deepintshield
73
73
 
74
- Unified Python SDK for DeepintShield — one import, any provider, any agent framework.
74
+ Unified Python SDK for DeepintShield - one import, any provider, any agent framework.
75
75
 
76
76
  `deepintshield` lets you keep writing idiomatic OpenAI / Anthropic / Bedrock /
77
77
  Google GenAI code **and** native agent-framework code (LangGraph, CrewAI,
@@ -79,20 +79,20 @@ OpenAI Agents SDK, LlamaIndex, AutoGen, PydanticAI) while automatically routing
79
79
  traffic through the DeepintShield gateway for guardrails, RAG filtering, agentic
80
80
  tool control, and agent identity.
81
81
 
82
- You pass **only two things — a virtual key and a base URL.** Everything else —
83
- the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy — is
82
+ You pass **only two things - a virtual key and a base URL.** Everything else -
83
+ the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy - is
84
84
  discovered from the gateway automatically. No identity GUIDs ever appear in your
85
85
  code.
86
86
 
87
87
  Protection comes in two layers:
88
88
 
89
- - **Transparent** — point any framework's *native* client at the gateway
89
+ - **Transparent** - point any framework's *native* client at the gateway
90
90
  (`base_url` + a one-line header injector). Chat, embeddings, input/output and
91
91
  RAG-prompt guardrails, observability and identity all run server-side with
92
92
  **zero changes** to your agent code. Works for Python frameworks *and* any
93
93
  OpenAI-compatible platform (n8n, Flowise, Dify, raw HTTP).
94
- - **Enforcement** — one wrapping line adds local **tool gating** (DENY /
95
- MASK / human approval) and **chunk-level RAG filtering** — the parts that
94
+ - **Enforcement** - one wrapping line adds local **tool gating** (DENY /
95
+ MASK / human approval) and **chunk-level RAG filtering** - the parts that
96
96
  physically can't be done at the wire because the tool runs in your process.
97
97
 
98
98
  Traffic defaults to **`https://app.deepintshield.com`**. Override the gateway
@@ -126,7 +126,7 @@ pip install 'deepintshield[all]' # everything
126
126
 
127
127
  ```bash
128
128
  export DEEPINTSHIELD_VIRTUAL_KEY="sk-..."
129
- # Optional — point at a self-hosted or staging gateway.
129
+ # Optional - point at a self-hosted or staging gateway.
130
130
  export DEEPINTSHIELD_BASE_URL="https://gateway.example.com"
131
131
  ```
132
132
 
@@ -251,7 +251,7 @@ allowed, raw = shield.rag.filter(query="What's the badge rule?", chunks=chunks)
251
251
  ### Guard a framework retriever (post-retrieval, one line)
252
252
 
253
253
  Wrap any LangChain / LlamaIndex retriever so unauthorised chunks are dropped
254
- *after* retrieval and *before* they reach the LLM — ACL/provenance filtering
254
+ *after* retrieval and *before* they reach the LLM - ACL/provenance filtering
255
255
  your retriever can't do itself:
256
256
 
257
257
  ```python
@@ -269,7 +269,7 @@ embedder.embed_query("text") # raises if the gatewa
269
269
  ```
270
270
 
271
271
  > If you obtain your embedder from a framework binder (below), input-side
272
- > screening already happens server-side — `guard_embedder` is for embedders you
272
+ > screening already happens server-side - `guard_embedder` is for embedders you
273
273
  > don't route through the gateway.
274
274
 
275
275
  ---
@@ -292,7 +292,7 @@ shield.autogen().model_client("gpt-4o-mini") # OpenAIChatCompletionClient
292
292
  shield.pydanticai().model("gpt-4o-mini")
293
293
  ```
294
294
 
295
- Framework-agnostic primitives — wire any SDK, in any language-compatible
295
+ Framework-agnostic primitives - wire any SDK, in any language-compatible
296
296
  client, by hand:
297
297
 
298
298
  ```python
@@ -302,23 +302,23 @@ headers = shield.create_headers(provider="anthropic") # Portkey-style header i
302
302
  ```
303
303
 
304
304
  > **Universal:** anything that speaks OpenAI-compatible HTTP gets transparent
305
- > protection with *zero code* — set the Base URL to `shield.endpoint("openai")`
305
+ > protection with *zero code* - set the Base URL to `shield.endpoint("openai")`
306
306
  > and the key to your VK. That covers n8n, Flowise, Dify and raw HTTP, not just
307
307
  > Python.
308
308
 
309
309
  ## Agentic tool enforcement
310
310
 
311
311
  The part a base URL can't do: gate **local** tool execution. Each gated call
312
- runs `decide()` first and the verdict maps to a Python outcome — `ALLOW` runs
312
+ runs `decide()` first and the verdict maps to a Python outcome - `ALLOW` runs
313
313
  the body, `MASK` redacts PII kwargs, `REQUIRE_APPROVAL` blocks for a human, and
314
314
  `DENY` raises `GuardrailDenied`.
315
315
 
316
- ### Zero extra code — enforcement is automatic and non-bypassable
316
+ ### Zero extra code - enforcement is automatic and non-bypassable
317
317
 
318
318
  The moment you construct `DeepintShield(...)`, the SDK installs guards for every
319
319
  agent framework you've imported (LangGraph, CrewAI, LlamaIndex, AutoGen,
320
320
  PydanticAI, the OpenAI Agents SDK, LiteLLM). After that, **compiling / building
321
- an agent yields an already-governed object** — you can't forget to gate it and
321
+ an agent yields an already-governed object** - you can't forget to gate it and
322
322
  you can't bypass it by invoking the un-governed one (there isn't one).
323
323
 
324
324
  ```python
@@ -334,7 +334,7 @@ g = StateGraph(State)
334
334
  g.add_node("read_step", crm_read)
335
335
  g.add_node("admin_step", admin_grant)
336
336
  ...
337
- app = g.compile() # auto-governed — every node now gated by the PDP
337
+ app = g.compile() # auto-governed - every node now gated by the PDP
338
338
 
339
339
  app.invoke({...}) # a DENY raises GuardrailDenied before the node runs
340
340
  ```
@@ -345,32 +345,32 @@ If you import a framework *after* building the client, call
345
345
  > **Security follows the implementation, not the label.** Each node/tool is
346
346
  > governed by its **function name** (`crm_read`), not the node label
347
347
  > (`read_step`), and the decision is bound to a fingerprint of the function's
348
- > **source** — so editing the body is detected and policies target `crm_read`.
348
+ > **source** - so editing the body is detected and policies target `crm_read`.
349
349
  >
350
350
  > **Trust boundary:** these client guards are cooperative defense-in-depth. A
351
351
  > determined process can un-patch them or call a tool's raw function, so the
352
352
  > gateway (MCP / LLM in the call path) remains the authoritative boundary.
353
353
 
354
- ### `govern()` — register + threat-scan + instrument (explicit, idempotent)
354
+ ### `govern()` - register + threat-scan + instrument (explicit, idempotent)
355
355
 
356
356
  `govern()` does everything the auto-guard does, explicitly: it **describes** the
357
357
  agent's declared tool surface, **registers** that blueprint with the server
358
- (which **threat-scans each tool's source** for RCE / shell-out / exfiltration —
359
- OWASP Agentic **T11 / T17** — server-side, ZDR), and **instruments** every call.
358
+ (which **threat-scans each tool's source** for RCE / shell-out / exfiltration -
359
+ OWASP Agentic **T11 / T17** - server-side, ZDR), and **instruments** every call.
360
360
 
361
361
  ```python
362
- app = shield.agentic.govern(app) # idempotent — safe alongside the auto-guard
362
+ app = shield.agentic.govern(app) # idempotent - safe alongside the auto-guard
363
363
  ```
364
364
 
365
365
  A tool whose source scans malicious is flagged (Agentic → Findings) and, when
366
- the workspace enables **Enforce code threat** (Rollout), denied — even if a
366
+ the workspace enables **Enforce code threat** (Rollout), denied - even if a
367
367
  policy would otherwise allow it. A tool called but never declared shows up as
368
368
  **ASI04 drift** under Agentic → Discovery.
369
369
 
370
- ### `guard()` — LangChain callback / in-place instrument
370
+ ### `guard()` - LangChain callback / in-place instrument
371
371
 
372
372
  `shield.agentic.guard()` (no argument) returns a native LangChain callback
373
- handler; attaching it once gates *every* tool the agent calls — the framework
373
+ handler; attaching it once gates *every* tool the agent calls - the framework
374
374
  supplies the tool name and the **gateway resolves the tier, policy, recovery
375
375
  cost and identity server-side**.
376
376
 
@@ -382,7 +382,7 @@ agent_executor.invoke({"input": "…"}, config={"callbacks": [guard]})
382
382
  `guard(target)` auto-detects and instruments a framework object in place:
383
383
 
384
384
  ```python
385
- shield.agentic.guard(compiled_graph) # LangGraph — gate every tool node
385
+ shield.agentic.guard(compiled_graph) # LangGraph - gate every tool node
386
386
  shield.agentic.guard(crewai_tools) # CrewAI BaseTools
387
387
  shield.agentic.guard(openai_agent) # OpenAI Agents FunctionTools
388
388
  shield.agentic.guard(pydantic_agent) # PydanticAI agent
@@ -435,7 +435,7 @@ When the virtual key is bound to an identity provider, the SDK auto-discovers
435
435
  the binding (`GET /api/agentic-security/vk-credential-info`), selects the right
436
436
  credential (Entra Agent ID FIC / ZeroID RFC 8693 / generic OIDC), and attaches a
437
437
  fresh `X-Agent-Token` on every decision. On Azure compute the Managed Identity
438
- is detected automatically — **no GUIDs, authority, or scopes in your code.**
438
+ is detected automatically - **no GUIDs, authority, or scopes in your code.**
439
439
 
440
440
  ```python
441
441
  info = shield.agentic.credential_info # ops visibility into the binding
@@ -473,7 +473,7 @@ app = graph.compile()
473
473
  ## Multimodal guardrails (transparent)
474
474
 
475
475
  Image generation, image edits, audio (TTS / transcription), video, embedding and
476
- rerank requests are guarded **at the gateway** — no SDK changes and no extra code.
476
+ rerank requests are guarded **at the gateway** - no SDK changes and no extra code.
477
477
  Keep using the native provider SDKs through DeepIntShield; when the operator
478
478
  enables `GUARDRAILS_MULTIMODAL`, the gateway evaluates the text these requests
479
479
  already carry (image/TTS/video prompts, transcripts) and the binary artifacts
@@ -482,7 +482,7 @@ themselves, blocking or flagging per your policies.
482
482
  ```python
483
483
  client = shield.openai()
484
484
 
485
- # Guarded automatically — the image prompt is evaluated before generation.
485
+ # Guarded automatically - the image prompt is evaluated before generation.
486
486
  img = client.images.generate(model="gpt-image-1", prompt="a serene mountain lake")
487
487
 
488
488
  # A blocked prompt surfaces as the provider SDK's normal HTTP error:
@@ -501,7 +501,7 @@ enforcing (`sync`) or observe-only (`shadow`).
501
501
 
502
502
  ## MCP
503
503
 
504
- Generic MCP support — works with any server connected to your DeepintShield
504
+ Generic MCP support - works with any server connected to your DeepintShield
505
505
  gateway. No per-server SDK code; the same `Tool` / `MCPClient` API serves
506
506
  DeepWiki, Context7, GitHub MCP, an internal one, and so on.
507
507
 
@@ -596,7 +596,7 @@ print(AgentExecutor(agent=agent, tools=mcp_tools).invoke(
596
596
  )["output"])
597
597
  ```
598
598
 
599
- LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
599
+ LangGraph reuses the same `mcp_tools` list - drop them into a `ToolNode`.
600
600
 
601
601
  ---
602
602
 
@@ -605,16 +605,16 @@ LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
605
605
  The SDK automatically participates in the gateway's two cost-reduction layers
606
606
  (both controlled by workspace switches under **Cost Optimization**):
607
607
 
608
- - **Provider prompt caching** — every chat client returned by `shield.openai()`,
608
+ - **Provider prompt caching** - every chat client returned by `shield.openai()`,
609
609
  `shield.anthropic()`, etc. ships an `httpx` request hook that injects
610
610
  Anthropic `cache_control` markers and an OpenAI `prompt_cache_key` so the
611
611
  provider reuses KV state for the static prompt prefix. Cached tokens come
612
612
  back at the provider's reduced rate (50% off OpenAI, 90% off Anthropic).
613
- - **Gemini context caching** — opt in with `shield.genai_cached()` (drop-in
613
+ - **Gemini context caching** - opt in with `shield.genai_cached()` (drop-in
614
614
  for `shield.genai()`). The wrapper manages the `cachedContents` resource
615
615
  lifecycle behind the scenes; the first call with a new static prefix runs
616
616
  normally and the next call within the TTL window reuses the cache.
617
- - **Semantic caching** — runs on the gateway; short-circuits requests whose
617
+ - **Semantic caching** - runs on the gateway; short-circuits requests whose
618
618
  embeddings match a previous response within the configured similarity
619
619
  threshold. The SDK doesn't need any code change to benefit; results flow
620
620
  back through the normal API.
@@ -1,6 +1,6 @@
1
1
  # deepintshield
2
2
 
3
- Unified Python SDK for DeepintShield — one import, any provider, any agent framework.
3
+ Unified Python SDK for DeepintShield - one import, any provider, any agent framework.
4
4
 
5
5
  `deepintshield` lets you keep writing idiomatic OpenAI / Anthropic / Bedrock /
6
6
  Google GenAI code **and** native agent-framework code (LangGraph, CrewAI,
@@ -8,20 +8,20 @@ OpenAI Agents SDK, LlamaIndex, AutoGen, PydanticAI) while automatically routing
8
8
  traffic through the DeepintShield gateway for guardrails, RAG filtering, agentic
9
9
  tool control, and agent identity.
10
10
 
11
- You pass **only two things — a virtual key and a base URL.** Everything else —
12
- the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy — is
11
+ You pass **only two things - a virtual key and a base URL.** Everything else -
12
+ the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy - is
13
13
  discovered from the gateway automatically. No identity GUIDs ever appear in your
14
14
  code.
15
15
 
16
16
  Protection comes in two layers:
17
17
 
18
- - **Transparent** — point any framework's *native* client at the gateway
18
+ - **Transparent** - point any framework's *native* client at the gateway
19
19
  (`base_url` + a one-line header injector). Chat, embeddings, input/output and
20
20
  RAG-prompt guardrails, observability and identity all run server-side with
21
21
  **zero changes** to your agent code. Works for Python frameworks *and* any
22
22
  OpenAI-compatible platform (n8n, Flowise, Dify, raw HTTP).
23
- - **Enforcement** — one wrapping line adds local **tool gating** (DENY /
24
- MASK / human approval) and **chunk-level RAG filtering** — the parts that
23
+ - **Enforcement** - one wrapping line adds local **tool gating** (DENY /
24
+ MASK / human approval) and **chunk-level RAG filtering** - the parts that
25
25
  physically can't be done at the wire because the tool runs in your process.
26
26
 
27
27
  Traffic defaults to **`https://app.deepintshield.com`**. Override the gateway
@@ -55,7 +55,7 @@ pip install 'deepintshield[all]' # everything
55
55
 
56
56
  ```bash
57
57
  export DEEPINTSHIELD_VIRTUAL_KEY="sk-..."
58
- # Optional — point at a self-hosted or staging gateway.
58
+ # Optional - point at a self-hosted or staging gateway.
59
59
  export DEEPINTSHIELD_BASE_URL="https://gateway.example.com"
60
60
  ```
61
61
 
@@ -180,7 +180,7 @@ allowed, raw = shield.rag.filter(query="What's the badge rule?", chunks=chunks)
180
180
  ### Guard a framework retriever (post-retrieval, one line)
181
181
 
182
182
  Wrap any LangChain / LlamaIndex retriever so unauthorised chunks are dropped
183
- *after* retrieval and *before* they reach the LLM — ACL/provenance filtering
183
+ *after* retrieval and *before* they reach the LLM - ACL/provenance filtering
184
184
  your retriever can't do itself:
185
185
 
186
186
  ```python
@@ -198,7 +198,7 @@ embedder.embed_query("text") # raises if the gatewa
198
198
  ```
199
199
 
200
200
  > If you obtain your embedder from a framework binder (below), input-side
201
- > screening already happens server-side — `guard_embedder` is for embedders you
201
+ > screening already happens server-side - `guard_embedder` is for embedders you
202
202
  > don't route through the gateway.
203
203
 
204
204
  ---
@@ -221,7 +221,7 @@ shield.autogen().model_client("gpt-4o-mini") # OpenAIChatCompletionClient
221
221
  shield.pydanticai().model("gpt-4o-mini")
222
222
  ```
223
223
 
224
- Framework-agnostic primitives — wire any SDK, in any language-compatible
224
+ Framework-agnostic primitives - wire any SDK, in any language-compatible
225
225
  client, by hand:
226
226
 
227
227
  ```python
@@ -231,23 +231,23 @@ headers = shield.create_headers(provider="anthropic") # Portkey-style header i
231
231
  ```
232
232
 
233
233
  > **Universal:** anything that speaks OpenAI-compatible HTTP gets transparent
234
- > protection with *zero code* — set the Base URL to `shield.endpoint("openai")`
234
+ > protection with *zero code* - set the Base URL to `shield.endpoint("openai")`
235
235
  > and the key to your VK. That covers n8n, Flowise, Dify and raw HTTP, not just
236
236
  > Python.
237
237
 
238
238
  ## Agentic tool enforcement
239
239
 
240
240
  The part a base URL can't do: gate **local** tool execution. Each gated call
241
- runs `decide()` first and the verdict maps to a Python outcome — `ALLOW` runs
241
+ runs `decide()` first and the verdict maps to a Python outcome - `ALLOW` runs
242
242
  the body, `MASK` redacts PII kwargs, `REQUIRE_APPROVAL` blocks for a human, and
243
243
  `DENY` raises `GuardrailDenied`.
244
244
 
245
- ### Zero extra code — enforcement is automatic and non-bypassable
245
+ ### Zero extra code - enforcement is automatic and non-bypassable
246
246
 
247
247
  The moment you construct `DeepintShield(...)`, the SDK installs guards for every
248
248
  agent framework you've imported (LangGraph, CrewAI, LlamaIndex, AutoGen,
249
249
  PydanticAI, the OpenAI Agents SDK, LiteLLM). After that, **compiling / building
250
- an agent yields an already-governed object** — you can't forget to gate it and
250
+ an agent yields an already-governed object** - you can't forget to gate it and
251
251
  you can't bypass it by invoking the un-governed one (there isn't one).
252
252
 
253
253
  ```python
@@ -263,7 +263,7 @@ g = StateGraph(State)
263
263
  g.add_node("read_step", crm_read)
264
264
  g.add_node("admin_step", admin_grant)
265
265
  ...
266
- app = g.compile() # auto-governed — every node now gated by the PDP
266
+ app = g.compile() # auto-governed - every node now gated by the PDP
267
267
 
268
268
  app.invoke({...}) # a DENY raises GuardrailDenied before the node runs
269
269
  ```
@@ -274,32 +274,32 @@ If you import a framework *after* building the client, call
274
274
  > **Security follows the implementation, not the label.** Each node/tool is
275
275
  > governed by its **function name** (`crm_read`), not the node label
276
276
  > (`read_step`), and the decision is bound to a fingerprint of the function's
277
- > **source** — so editing the body is detected and policies target `crm_read`.
277
+ > **source** - so editing the body is detected and policies target `crm_read`.
278
278
  >
279
279
  > **Trust boundary:** these client guards are cooperative defense-in-depth. A
280
280
  > determined process can un-patch them or call a tool's raw function, so the
281
281
  > gateway (MCP / LLM in the call path) remains the authoritative boundary.
282
282
 
283
- ### `govern()` — register + threat-scan + instrument (explicit, idempotent)
283
+ ### `govern()` - register + threat-scan + instrument (explicit, idempotent)
284
284
 
285
285
  `govern()` does everything the auto-guard does, explicitly: it **describes** the
286
286
  agent's declared tool surface, **registers** that blueprint with the server
287
- (which **threat-scans each tool's source** for RCE / shell-out / exfiltration —
288
- OWASP Agentic **T11 / T17** — server-side, ZDR), and **instruments** every call.
287
+ (which **threat-scans each tool's source** for RCE / shell-out / exfiltration -
288
+ OWASP Agentic **T11 / T17** - server-side, ZDR), and **instruments** every call.
289
289
 
290
290
  ```python
291
- app = shield.agentic.govern(app) # idempotent — safe alongside the auto-guard
291
+ app = shield.agentic.govern(app) # idempotent - safe alongside the auto-guard
292
292
  ```
293
293
 
294
294
  A tool whose source scans malicious is flagged (Agentic → Findings) and, when
295
- the workspace enables **Enforce code threat** (Rollout), denied — even if a
295
+ the workspace enables **Enforce code threat** (Rollout), denied - even if a
296
296
  policy would otherwise allow it. A tool called but never declared shows up as
297
297
  **ASI04 drift** under Agentic → Discovery.
298
298
 
299
- ### `guard()` — LangChain callback / in-place instrument
299
+ ### `guard()` - LangChain callback / in-place instrument
300
300
 
301
301
  `shield.agentic.guard()` (no argument) returns a native LangChain callback
302
- handler; attaching it once gates *every* tool the agent calls — the framework
302
+ handler; attaching it once gates *every* tool the agent calls - the framework
303
303
  supplies the tool name and the **gateway resolves the tier, policy, recovery
304
304
  cost and identity server-side**.
305
305
 
@@ -311,7 +311,7 @@ agent_executor.invoke({"input": "…"}, config={"callbacks": [guard]})
311
311
  `guard(target)` auto-detects and instruments a framework object in place:
312
312
 
313
313
  ```python
314
- shield.agentic.guard(compiled_graph) # LangGraph — gate every tool node
314
+ shield.agentic.guard(compiled_graph) # LangGraph - gate every tool node
315
315
  shield.agentic.guard(crewai_tools) # CrewAI BaseTools
316
316
  shield.agentic.guard(openai_agent) # OpenAI Agents FunctionTools
317
317
  shield.agentic.guard(pydantic_agent) # PydanticAI agent
@@ -364,7 +364,7 @@ When the virtual key is bound to an identity provider, the SDK auto-discovers
364
364
  the binding (`GET /api/agentic-security/vk-credential-info`), selects the right
365
365
  credential (Entra Agent ID FIC / ZeroID RFC 8693 / generic OIDC), and attaches a
366
366
  fresh `X-Agent-Token` on every decision. On Azure compute the Managed Identity
367
- is detected automatically — **no GUIDs, authority, or scopes in your code.**
367
+ is detected automatically - **no GUIDs, authority, or scopes in your code.**
368
368
 
369
369
  ```python
370
370
  info = shield.agentic.credential_info # ops visibility into the binding
@@ -402,7 +402,7 @@ app = graph.compile()
402
402
  ## Multimodal guardrails (transparent)
403
403
 
404
404
  Image generation, image edits, audio (TTS / transcription), video, embedding and
405
- rerank requests are guarded **at the gateway** — no SDK changes and no extra code.
405
+ rerank requests are guarded **at the gateway** - no SDK changes and no extra code.
406
406
  Keep using the native provider SDKs through DeepIntShield; when the operator
407
407
  enables `GUARDRAILS_MULTIMODAL`, the gateway evaluates the text these requests
408
408
  already carry (image/TTS/video prompts, transcripts) and the binary artifacts
@@ -411,7 +411,7 @@ themselves, blocking or flagging per your policies.
411
411
  ```python
412
412
  client = shield.openai()
413
413
 
414
- # Guarded automatically — the image prompt is evaluated before generation.
414
+ # Guarded automatically - the image prompt is evaluated before generation.
415
415
  img = client.images.generate(model="gpt-image-1", prompt="a serene mountain lake")
416
416
 
417
417
  # A blocked prompt surfaces as the provider SDK's normal HTTP error:
@@ -430,7 +430,7 @@ enforcing (`sync`) or observe-only (`shadow`).
430
430
 
431
431
  ## MCP
432
432
 
433
- Generic MCP support — works with any server connected to your DeepintShield
433
+ Generic MCP support - works with any server connected to your DeepintShield
434
434
  gateway. No per-server SDK code; the same `Tool` / `MCPClient` API serves
435
435
  DeepWiki, Context7, GitHub MCP, an internal one, and so on.
436
436
 
@@ -525,7 +525,7 @@ print(AgentExecutor(agent=agent, tools=mcp_tools).invoke(
525
525
  )["output"])
526
526
  ```
527
527
 
528
- LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
528
+ LangGraph reuses the same `mcp_tools` list - drop them into a `ToolNode`.
529
529
 
530
530
  ---
531
531
 
@@ -534,16 +534,16 @@ LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
534
534
  The SDK automatically participates in the gateway's two cost-reduction layers
535
535
  (both controlled by workspace switches under **Cost Optimization**):
536
536
 
537
- - **Provider prompt caching** — every chat client returned by `shield.openai()`,
537
+ - **Provider prompt caching** - every chat client returned by `shield.openai()`,
538
538
  `shield.anthropic()`, etc. ships an `httpx` request hook that injects
539
539
  Anthropic `cache_control` markers and an OpenAI `prompt_cache_key` so the
540
540
  provider reuses KV state for the static prompt prefix. Cached tokens come
541
541
  back at the provider's reduced rate (50% off OpenAI, 90% off Anthropic).
542
- - **Gemini context caching** — opt in with `shield.genai_cached()` (drop-in
542
+ - **Gemini context caching** - opt in with `shield.genai_cached()` (drop-in
543
543
  for `shield.genai()`). The wrapper manages the `cachedContents` resource
544
544
  lifecycle behind the scenes; the first call with a new static prefix runs
545
545
  normally and the next call within the TTL window reuses the cache.
546
- - **Semantic caching** — runs on the gateway; short-circuits requests whose
546
+ - **Semantic caching** - runs on the gateway; short-circuits requests whose
547
547
  embeddings match a previous response within the configured similarity
548
548
  threshold. The SDK doesn't need any code change to benefit; results flow
549
549
  back through the normal API.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deepintshield"
7
- version = "2.3.0"
7
+ version = "2.4.0"
8
8
  description = "Unified Python SDK for routing chat, RAG, agentic tool-gating, identity, and MCP traffic through DeepintShield — drop-in across the top agentic frameworks."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1 @@
1
+ __version__ = "2.4.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepintshield
3
- Version: 2.3.0
3
+ Version: 2.4.0
4
4
  Summary: Unified Python SDK for routing chat, RAG, agentic tool-gating, identity, and MCP traffic through DeepintShield — drop-in across the top agentic frameworks.
5
5
  Author: DeepintShield
6
6
  License: Apache-2.0
@@ -71,7 +71,7 @@ Dynamic: license-file
71
71
 
72
72
  # deepintshield
73
73
 
74
- Unified Python SDK for DeepintShield — one import, any provider, any agent framework.
74
+ Unified Python SDK for DeepintShield - one import, any provider, any agent framework.
75
75
 
76
76
  `deepintshield` lets you keep writing idiomatic OpenAI / Anthropic / Bedrock /
77
77
  Google GenAI code **and** native agent-framework code (LangGraph, CrewAI,
@@ -79,20 +79,20 @@ OpenAI Agents SDK, LlamaIndex, AutoGen, PydanticAI) while automatically routing
79
79
  traffic through the DeepintShield gateway for guardrails, RAG filtering, agentic
80
80
  tool control, and agent identity.
81
81
 
82
- You pass **only two things — a virtual key and a base URL.** Everything else —
83
- the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy — is
82
+ You pass **only two things - a virtual key and a base URL.** Everything else -
83
+ the Entra / ZeroID / OIDC identity binding, tenant, scopes, and policy - is
84
84
  discovered from the gateway automatically. No identity GUIDs ever appear in your
85
85
  code.
86
86
 
87
87
  Protection comes in two layers:
88
88
 
89
- - **Transparent** — point any framework's *native* client at the gateway
89
+ - **Transparent** - point any framework's *native* client at the gateway
90
90
  (`base_url` + a one-line header injector). Chat, embeddings, input/output and
91
91
  RAG-prompt guardrails, observability and identity all run server-side with
92
92
  **zero changes** to your agent code. Works for Python frameworks *and* any
93
93
  OpenAI-compatible platform (n8n, Flowise, Dify, raw HTTP).
94
- - **Enforcement** — one wrapping line adds local **tool gating** (DENY /
95
- MASK / human approval) and **chunk-level RAG filtering** — the parts that
94
+ - **Enforcement** - one wrapping line adds local **tool gating** (DENY /
95
+ MASK / human approval) and **chunk-level RAG filtering** - the parts that
96
96
  physically can't be done at the wire because the tool runs in your process.
97
97
 
98
98
  Traffic defaults to **`https://app.deepintshield.com`**. Override the gateway
@@ -126,7 +126,7 @@ pip install 'deepintshield[all]' # everything
126
126
 
127
127
  ```bash
128
128
  export DEEPINTSHIELD_VIRTUAL_KEY="sk-..."
129
- # Optional — point at a self-hosted or staging gateway.
129
+ # Optional - point at a self-hosted or staging gateway.
130
130
  export DEEPINTSHIELD_BASE_URL="https://gateway.example.com"
131
131
  ```
132
132
 
@@ -251,7 +251,7 @@ allowed, raw = shield.rag.filter(query="What's the badge rule?", chunks=chunks)
251
251
  ### Guard a framework retriever (post-retrieval, one line)
252
252
 
253
253
  Wrap any LangChain / LlamaIndex retriever so unauthorised chunks are dropped
254
- *after* retrieval and *before* they reach the LLM — ACL/provenance filtering
254
+ *after* retrieval and *before* they reach the LLM - ACL/provenance filtering
255
255
  your retriever can't do itself:
256
256
 
257
257
  ```python
@@ -269,7 +269,7 @@ embedder.embed_query("text") # raises if the gatewa
269
269
  ```
270
270
 
271
271
  > If you obtain your embedder from a framework binder (below), input-side
272
- > screening already happens server-side — `guard_embedder` is for embedders you
272
+ > screening already happens server-side - `guard_embedder` is for embedders you
273
273
  > don't route through the gateway.
274
274
 
275
275
  ---
@@ -292,7 +292,7 @@ shield.autogen().model_client("gpt-4o-mini") # OpenAIChatCompletionClient
292
292
  shield.pydanticai().model("gpt-4o-mini")
293
293
  ```
294
294
 
295
- Framework-agnostic primitives — wire any SDK, in any language-compatible
295
+ Framework-agnostic primitives - wire any SDK, in any language-compatible
296
296
  client, by hand:
297
297
 
298
298
  ```python
@@ -302,23 +302,23 @@ headers = shield.create_headers(provider="anthropic") # Portkey-style header i
302
302
  ```
303
303
 
304
304
  > **Universal:** anything that speaks OpenAI-compatible HTTP gets transparent
305
- > protection with *zero code* — set the Base URL to `shield.endpoint("openai")`
305
+ > protection with *zero code* - set the Base URL to `shield.endpoint("openai")`
306
306
  > and the key to your VK. That covers n8n, Flowise, Dify and raw HTTP, not just
307
307
  > Python.
308
308
 
309
309
  ## Agentic tool enforcement
310
310
 
311
311
  The part a base URL can't do: gate **local** tool execution. Each gated call
312
- runs `decide()` first and the verdict maps to a Python outcome — `ALLOW` runs
312
+ runs `decide()` first and the verdict maps to a Python outcome - `ALLOW` runs
313
313
  the body, `MASK` redacts PII kwargs, `REQUIRE_APPROVAL` blocks for a human, and
314
314
  `DENY` raises `GuardrailDenied`.
315
315
 
316
- ### Zero extra code — enforcement is automatic and non-bypassable
316
+ ### Zero extra code - enforcement is automatic and non-bypassable
317
317
 
318
318
  The moment you construct `DeepintShield(...)`, the SDK installs guards for every
319
319
  agent framework you've imported (LangGraph, CrewAI, LlamaIndex, AutoGen,
320
320
  PydanticAI, the OpenAI Agents SDK, LiteLLM). After that, **compiling / building
321
- an agent yields an already-governed object** — you can't forget to gate it and
321
+ an agent yields an already-governed object** - you can't forget to gate it and
322
322
  you can't bypass it by invoking the un-governed one (there isn't one).
323
323
 
324
324
  ```python
@@ -334,7 +334,7 @@ g = StateGraph(State)
334
334
  g.add_node("read_step", crm_read)
335
335
  g.add_node("admin_step", admin_grant)
336
336
  ...
337
- app = g.compile() # auto-governed — every node now gated by the PDP
337
+ app = g.compile() # auto-governed - every node now gated by the PDP
338
338
 
339
339
  app.invoke({...}) # a DENY raises GuardrailDenied before the node runs
340
340
  ```
@@ -345,32 +345,32 @@ If you import a framework *after* building the client, call
345
345
  > **Security follows the implementation, not the label.** Each node/tool is
346
346
  > governed by its **function name** (`crm_read`), not the node label
347
347
  > (`read_step`), and the decision is bound to a fingerprint of the function's
348
- > **source** — so editing the body is detected and policies target `crm_read`.
348
+ > **source** - so editing the body is detected and policies target `crm_read`.
349
349
  >
350
350
  > **Trust boundary:** these client guards are cooperative defense-in-depth. A
351
351
  > determined process can un-patch them or call a tool's raw function, so the
352
352
  > gateway (MCP / LLM in the call path) remains the authoritative boundary.
353
353
 
354
- ### `govern()` — register + threat-scan + instrument (explicit, idempotent)
354
+ ### `govern()` - register + threat-scan + instrument (explicit, idempotent)
355
355
 
356
356
  `govern()` does everything the auto-guard does, explicitly: it **describes** the
357
357
  agent's declared tool surface, **registers** that blueprint with the server
358
- (which **threat-scans each tool's source** for RCE / shell-out / exfiltration —
359
- OWASP Agentic **T11 / T17** — server-side, ZDR), and **instruments** every call.
358
+ (which **threat-scans each tool's source** for RCE / shell-out / exfiltration -
359
+ OWASP Agentic **T11 / T17** - server-side, ZDR), and **instruments** every call.
360
360
 
361
361
  ```python
362
- app = shield.agentic.govern(app) # idempotent — safe alongside the auto-guard
362
+ app = shield.agentic.govern(app) # idempotent - safe alongside the auto-guard
363
363
  ```
364
364
 
365
365
  A tool whose source scans malicious is flagged (Agentic → Findings) and, when
366
- the workspace enables **Enforce code threat** (Rollout), denied — even if a
366
+ the workspace enables **Enforce code threat** (Rollout), denied - even if a
367
367
  policy would otherwise allow it. A tool called but never declared shows up as
368
368
  **ASI04 drift** under Agentic → Discovery.
369
369
 
370
- ### `guard()` — LangChain callback / in-place instrument
370
+ ### `guard()` - LangChain callback / in-place instrument
371
371
 
372
372
  `shield.agentic.guard()` (no argument) returns a native LangChain callback
373
- handler; attaching it once gates *every* tool the agent calls — the framework
373
+ handler; attaching it once gates *every* tool the agent calls - the framework
374
374
  supplies the tool name and the **gateway resolves the tier, policy, recovery
375
375
  cost and identity server-side**.
376
376
 
@@ -382,7 +382,7 @@ agent_executor.invoke({"input": "…"}, config={"callbacks": [guard]})
382
382
  `guard(target)` auto-detects and instruments a framework object in place:
383
383
 
384
384
  ```python
385
- shield.agentic.guard(compiled_graph) # LangGraph — gate every tool node
385
+ shield.agentic.guard(compiled_graph) # LangGraph - gate every tool node
386
386
  shield.agentic.guard(crewai_tools) # CrewAI BaseTools
387
387
  shield.agentic.guard(openai_agent) # OpenAI Agents FunctionTools
388
388
  shield.agentic.guard(pydantic_agent) # PydanticAI agent
@@ -435,7 +435,7 @@ When the virtual key is bound to an identity provider, the SDK auto-discovers
435
435
  the binding (`GET /api/agentic-security/vk-credential-info`), selects the right
436
436
  credential (Entra Agent ID FIC / ZeroID RFC 8693 / generic OIDC), and attaches a
437
437
  fresh `X-Agent-Token` on every decision. On Azure compute the Managed Identity
438
- is detected automatically — **no GUIDs, authority, or scopes in your code.**
438
+ is detected automatically - **no GUIDs, authority, or scopes in your code.**
439
439
 
440
440
  ```python
441
441
  info = shield.agentic.credential_info # ops visibility into the binding
@@ -473,7 +473,7 @@ app = graph.compile()
473
473
  ## Multimodal guardrails (transparent)
474
474
 
475
475
  Image generation, image edits, audio (TTS / transcription), video, embedding and
476
- rerank requests are guarded **at the gateway** — no SDK changes and no extra code.
476
+ rerank requests are guarded **at the gateway** - no SDK changes and no extra code.
477
477
  Keep using the native provider SDKs through DeepIntShield; when the operator
478
478
  enables `GUARDRAILS_MULTIMODAL`, the gateway evaluates the text these requests
479
479
  already carry (image/TTS/video prompts, transcripts) and the binary artifacts
@@ -482,7 +482,7 @@ themselves, blocking or flagging per your policies.
482
482
  ```python
483
483
  client = shield.openai()
484
484
 
485
- # Guarded automatically — the image prompt is evaluated before generation.
485
+ # Guarded automatically - the image prompt is evaluated before generation.
486
486
  img = client.images.generate(model="gpt-image-1", prompt="a serene mountain lake")
487
487
 
488
488
  # A blocked prompt surfaces as the provider SDK's normal HTTP error:
@@ -501,7 +501,7 @@ enforcing (`sync`) or observe-only (`shadow`).
501
501
 
502
502
  ## MCP
503
503
 
504
- Generic MCP support — works with any server connected to your DeepintShield
504
+ Generic MCP support - works with any server connected to your DeepintShield
505
505
  gateway. No per-server SDK code; the same `Tool` / `MCPClient` API serves
506
506
  DeepWiki, Context7, GitHub MCP, an internal one, and so on.
507
507
 
@@ -596,7 +596,7 @@ print(AgentExecutor(agent=agent, tools=mcp_tools).invoke(
596
596
  )["output"])
597
597
  ```
598
598
 
599
- LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
599
+ LangGraph reuses the same `mcp_tools` list - drop them into a `ToolNode`.
600
600
 
601
601
  ---
602
602
 
@@ -605,16 +605,16 @@ LangGraph reuses the same `mcp_tools` list — drop them into a `ToolNode`.
605
605
  The SDK automatically participates in the gateway's two cost-reduction layers
606
606
  (both controlled by workspace switches under **Cost Optimization**):
607
607
 
608
- - **Provider prompt caching** — every chat client returned by `shield.openai()`,
608
+ - **Provider prompt caching** - every chat client returned by `shield.openai()`,
609
609
  `shield.anthropic()`, etc. ships an `httpx` request hook that injects
610
610
  Anthropic `cache_control` markers and an OpenAI `prompt_cache_key` so the
611
611
  provider reuses KV state for the static prompt prefix. Cached tokens come
612
612
  back at the provider's reduced rate (50% off OpenAI, 90% off Anthropic).
613
- - **Gemini context caching** — opt in with `shield.genai_cached()` (drop-in
613
+ - **Gemini context caching** - opt in with `shield.genai_cached()` (drop-in
614
614
  for `shield.genai()`). The wrapper manages the `cachedContents` resource
615
615
  lifecycle behind the scenes; the first call with a new static prefix runs
616
616
  normally and the next call within the TTL window reuses the cache.
617
- - **Semantic caching** — runs on the gateway; short-circuits requests whose
617
+ - **Semantic caching** - runs on the gateway; short-circuits requests whose
618
618
  embeddings match a previous response within the configured similarity
619
619
  threshold. The SDK doesn't need any code change to benefit; results flow
620
620
  back through the normal API.
@@ -1 +0,0 @@
1
- __version__ = "2.3.0"
File without changes
File without changes