All notable changes to the unplug-ai SDK.
- The
unplug-ai[ag2]extra, its nightly live-integration leg, and its row in INTEGRATIONS. AG2 1.0 renamed its import fromautogentoag2, so the pin had to track a moving namespace to buy very little: the adapter never imported the framework. Breaking for anyone installingunplug-ai[ag2]; installag2directly alongsideunplug-aiinstead.unplug.integrations.ag2is unchanged and still supported, andexamples/ag2_hooks_demo.pyshows registering the hooks on a realConversableAgentbehind a lazy import that accepts either module name.
injectionscanner no longer flags ordinary non-English text (Cyrillic, CJK) asinvisible_text; the trigger is narrowed to genuine zero-width/bidi control characters and mixed-script homoglyph smuggling, the finding span is scoped to the offending characters instead of the whole message, and an interleaved evasion run (e.g. zero-width chars between every letter) emits one finding covering the outer span so redaction replaces it with a single BLOCKED tag (#121)injectionscanner merges adjacent evasion spans only when they sit within a short gap (e.g. zero-width chars interleaved between the letters of a word), so two distant evasion points no longer collapse into one span that swallows ordinary text between them (#123)
- Safe-prefix cache: re-scan overlap at chunk boundaries and scope cache keys by source + policy fingerprint so split injection phrases and cross-source ALLOW reuse cannot bypass detection (#87, fixes #82/#83)
- Per-request
scanners=allowlist no longer sticks on the sharedExecutionContext; omittedscannersclears the allowlist so later scans use the full configured set (#88, fixes #84) Guard(config=GuardConfig(mode=...))keeps the configured mode whenmode=is not passed;strict_scanner_allowlistloads from TOML/build_config; unknown[guard]keys raiseConfigError(#89, fixes #85)- Judge
action=block/review/allowclamps finding scores so declared verdicts drive enforcement even when the LLM returns an inconsistent score (#90, fixes #86) - Follow-up hardening from review debt: cache policy fingerprint + prefix overlap ≥ 1, strict-allowlist coercion, judge score enforcement, skip sensitive-context boost on
llm_judge, hold ML inference lock throughpredict_batch, validate indexed shard checkpoints (#91)
- Public
LimitConfig/ BYOLLM judge surface (unplug,unplug.api.limits,unplug.api.judge) with docs, example, and TOML notes (#80) - Focused injection regex patterns from neuralchemy FN sampling; bidi control stripping in the normalizer (#80)
- Pre-0.6.0 local test harness:
make test-frameworks,test-ml-harness,smoke-ml-hooks,test-all-localplusdocs/TESTING_HARNESS.md(#92)
- Post-merge review follow-ups across promote/Phase C:
unplug-scanpin, AG2 multimodal redaction, model download flock/staging, tighterinstructions_updated_supersederegex,NORMALIZER_VERSIONbump, sharded safetensors checkpoints (#81)
- Eval docs refreshed (
EVAL_PHASE_C.md/ benchmarks); regex neuralchemy recall/F1 improved modestly after pattern expansion (#80)
- Coverage tests for v1.0 deprecation shim re-exports (
unplug.core.*,guard_scan,scanner,safeguards) - Offline synthetic BIOES checkpoint fixture for ML unit tests (no real weights required)
- CI wheel-only resolve for
unplug-ai[ml]on Python 3.13 (catches sdist-only breakage)
- Dead modules:
providers/scrape.py,providers/content/server.py,optional/haystack.py(unused; useguards/scrape,providers/content/firecrawl,integrations/haystack) - Config fields
judge_enabled,pipeline.judge_timeout(no-op; passjudge=toGuard()instead)
- Unknown
active_modeltier names now raiseConfigErrorwith valid catalog tiers instead of silently running without ML - Widen
transformersextra constraint to>=4.44,<6(was<5.13) so newer minors stay installable - Drop published
devoptional-extra; test/lint tools live in thedevdependency-group (uv sync --dev) - Deprecated config:
judge_enabled,pipeline.judge_timeout,pipeline.fail_closedwarn and are ignored (removed in v1.0);guard.fail_closed=false/fail_mode="open"unchanged - Docs:
unplug-ai[scrape]package name in Firecrawl docstring; Atomic Agents Python ≥3.12 install gate; Semantic Kernelpybars4wheel-only note
- Agent usability:
Guard.init()docstring no longer claims auto-instrumentation; docs standardize onfrom unplug import ...for apps andunplug.api.*for server/MCP dependents; routineREVIEWpipeline outcomes log at INFO instead of WARNING - ML inference hardening: BIOES decode no longer crashes on checkpoints without
*-INJlabels; label maps are validated at load with a clearModelError; forced torch devices are validated (ConfigError);ModelProvider/SpanInferenceModelload is thread-safe; ML modules log device/tokenizer fallbacks and import torch viaunplug.optional.mlhelpers - Model store hardening: corrupt manifests no longer crash Guard or
unplug-models; checkpoint validation requires weight files; atomic manifest writes and download swaps preserve existing installs on failure;list_statuscorrectly reports stale revisions as upgrade-available; invalidUNPLUG_MODEL_PATHlogs a warning; CLI download errors distinguish missing ML extras from network/repo failures
- Python 3.13:
unplug-ai[ml]/[all]install without a Rust toolchain — widentransformersconstraint to>=4.44,<5.13sotokenizersresolves to a cp313 wheel (was pinned viatransformers>=4.44,<4.45→tokenizers==0.19.1)
- Pin bundled model catalog to immutable Hugging Face commit SHAs under
Unplug-AI/; drop unpublished medium/large tiers that pointed at a non-existent org
- Beginner onboarding:
docs/GETTING_STARTED.md(5-minute path) - Agent-host guide:
docs/AGENT_ACTIONS.md(ALLOW / REVIEW / BLOCK +ApprovalProvider) HookDecision.needs_reviewandHookDecision.is_blockhelpers for integration adapters- Stable public API facades under
unplug.api.*for policy, privacy, cache, boundaries, normalization, encoding, and ML runtime imports used by server/MCP dependents (docs/PUBLIC_API.md)
- Integrations hub: pick-your-path table, PyPI doc links, REVIEW vs BLOCK section
unplug-audit --probesskips FP/encoding batteries when ML is inactive (boundary probes still run); clearer CLI hintsunplug.example.toml: ML settings commented by default (regex-only copy-paste safe)- PyPI
DocumentationURL points to Getting Started;scan_context_filetuple examples fixed in READMEs unplug-scan-actiondefault version pin bumped to>=0.5.0,<0.6CONTRIBUTING.md: full framework extras table
- Integration adapters for seven more agent frameworks: OpenAI Agents SDK (
unplug.integrations.openai_agents, native input/output guardrails), LangChain (unplug.integrations.langchain, LCEL Runnable guards + a tool-gating callback handler), Google ADK (unplug.integrations.google_adk,before_model/before_toolcallbacks), smolagents (unplug.integrations.smolagents, task gate +final_answer_checks+ tool guard), DSPy (unplug.integrations.dspy,unplug_guard_modulewrapping +dspy_guard_toolfor ReAct), Strands Agents (unplug.integrations.strands, aHookProviderthat cancels destructive tool calls), and Letta (unplug.integrations.letta, client-boundary message/response guards) - Per-framework optional extras
unplug-ai[openai-agents],[langchain],[google-adk],[smolagents],[dspy],[strands],[letta], all folded into theintegrationsmeta-extra - Three more framework adapters: Griptape (
unplug.integrations.griptape,on_before_run/on_after_runtask hooks + tool gate), AG2 (unplug.integrations.ag2,ConversableAgentmessage hooks +ag2_guard_tool, distinct from the Microsoftautogenextra), and Atomic Agents (unplug.integrations.atomic_agents, Pydantic IO-schema input/output guards) - Optional extras
unplug-ai[griptape],[ag2],[atomic-agents](the last gated to Python ≥3.12, which the library requires), folded into theintegrationsmeta-extra - Per-framework guides under
integrations/and runnable demos underexamples/for each new adapter - Expanded the agent security matrix from 40 to 72 angles (ten new framework bindings), plus live tests and dedicated
Integrations (live)CI legs for each new extra
- Agent-framework integration hub (
unplug.integrations.*): framework-agnosticAgentHooksplus adapters for LangGraph, Agno, CrewAI, AutoGen, LlamaIndex, Pydantic AI, Semantic Kernel, and a custom-loop guide - Per-framework optional extras (
unplug-ai[langgraph],[agno],[crewai],[autogen],[llama-index],[pydantic-ai],[semantic-kernel],[mcp]) and anintegrationsmeta-extra that installs them all - 40-angle agent security matrix (
tests/security/test_agent_integration_matrix.py) - Live per-framework integration tests (
tests/optional/live/) behind a dedicatedIntegrations (live)CI job (per-framework matrix,requires_integrationsmarker), with exit-5 tolerance for frameworks that are unimportable under our pinned deps - Integrations documentation hub under
integrations/(per-framework guides +TESTING.md)
allextra now installs capability extras only (ml,scrape,litellm,yara,haystack,presidio); agent-framework adapters install via theintegrationsextra (or one at a time) so the core dependency tree and default CI matrix stay lean
ScanResult.degradedandScanResult.degraded_layers— surface when configured protection layers were unavailable- Token privacy filter (
build_privacy_filter,ModelPrivacyFilter,HeuristicPrivacyFilter) behind optionalpresidio/ ML extras MIGRATION.md— API stability tiers, deprecated import paths, and v1.0 removal timelinerefresh_scan_resultstable export atunplug.api.results- README benchmark table separating regex-only vs ML recall-gate metrics
with_tiny()recall-gate preset tuned for higher ML recall on injection
- Privacy filter thread-safe model load and
max_lengthforwarding - Benchmark ML guard pipeline isolation and exfil demo output edge cases
- Flat
unplug.core.*shim imports emitDeprecationWarning; canonical subpackages are preferred unplug.guard_scanemits deprecation warning — useunplug.api.results- Judge default model updated to
gpt-5.4-nano - Audit remediation bundle (#41–#42): degradation metadata, privacy filter, scan CLI hardening
unplug-scan-prCLI — scan changed agent/MCP config files in PRs (regex-only Guard)- GitHub composite action
.github/actions/unplug-scanand reusableworkflow_callworkflow strict_scanner_allowlistconfig — raiseConfigErrorwhen mandatory input scanners are omitted- Model cache revision +
config.jsondigest verification inModelStore - Judge sanitization — strip scanner finding evidence before BYOLLM prompts
ScanPolicy()default whencontext.scan_policyis None — USER secret scanning no longer silently disabledConfigErrorfrom strict allowlist propagates fromGuard.scan_request(not swallowed by fail-closed)UnplugClient.batch_scanraisesServerErroron missing or invalidresultskey- URL scanner evasion normalize with homoglyph/punycode patterns on raw text
- Patch release bundling audit remediation (#27–#29) and Phase B distribution work (#30)
- ABSTAIN semantics:
ScanResult.safeisFalseforAction.ABSTAINby default; setpolicy.abstain_is_safe = truefor legacy pass-through - ML gate default:
always_below_high = falseandgray_low = 0.3— usepreset = "recall"oralways_below_high = truefor max recall - Unified thresholds: input, output, and tool-call pipelines share
ScanPolicyviadecide_action() - Tool approval: caller
approved=Trueis ignored; useApprovalProviderto clearREVIEW - Hooks: non-
ALLOWactions block; retrieved content returns redacted text, not raw wrapped input - Haystack ingest:
strict_ingest=true(default) requiresaction == ALLOWandsafe - Config:
[toolchain]and[collusion]TOML sections load intoGuardConfig; unknown scanner names fail at init fail_closed/fail_mode="open": deprecated — errors always fail closed
scan_user_secretsonScanPolicy— USER input scanned for secret-shaped leakage patternsGuard.ml_degradedwhenactive_modelis set but ML failed to load- Pipeline-level normalization cache (one normalize pass per input scan)
ServerError,ScanPolicy,ConfigErrorexported from top-levelunplugsrc/unplug/py.typedfor PEP 561
- Tagline: "Unplug the bad AI" (README, pyproject, package docstring)
- Canonical namespace:
unplug.scanners.*replacesunplug.safeguards.* - Core layout:
core/split into subpackages (taint/,normalize/,policy/,agent/,privacy/,runtime/,redaction/) with flat shims until v1.0 - Patterns externalized: Regex lists in
data/patterns/*.yaml; maps indata/maps/*.toml; loaded viacore/pattern_loader.py - Optional deps: Fail-loud
unplug.optional.*modules replaceis_available()soft skips - YARA rules: Bundled under
data/yara_rules/
unplug.safeguards— import fromunplug.scanners(removed v1.0)SafeguardRegistry— useScannerRegistry(removed v1.0)- Flat
unplug.core.*shim modules — import from subpackages (removed v1.0)
CODE_OF_CONDUCT.md,SECURITY.mdat repo rootdocs/ARCHITECTURE.md,RESTRUCTURE_PLAN.md,LOGIC_AUDIT.md- Runtime dependency:
pyyaml tests/unit/core/test_pattern_loader.py- Dev branch workflow; PyPI publish from
main - Safeguard registry, ML span model preview, agent hardening suite