diff --git a/packages/dify-plugin-tealtiger/examples/workflow_export.yml b/packages/dify-plugin-tealtiger/examples/workflow_export.yml new file mode 100644 index 0000000..0208cd5 --- /dev/null +++ b/packages/dify-plugin-tealtiger/examples/workflow_export.yml @@ -0,0 +1,72 @@ +app: + description: Example workflow demonstrating TealTiger governance gate. + icon: 🛡️ + icon_background: '#FFEAD5' + mode: workflow + name: TealTiger Governance Workflow +workflow: + features: + file_upload: + image: + enabled: false + graph: + edges: + - id: start_to_tealtiger + source: start + target: tealtiger_governance + - id: tealtiger_to_llm + source: tealtiger_governance + target: llm_generation + condition: + rules: + - variable: tealtiger_governance.decision + operator: equal + value: "ALLOW" + - id: tealtiger_to_end + source: tealtiger_governance + target: end_blocked + condition: + rules: + - variable: tealtiger_governance.decision + operator: equal + value: "DENY" + nodes: + - id: start + position: + x: 0 + y: 0 + type: start + data: + variables: + - name: user_input + type: string + - id: tealtiger_governance + position: + x: 300 + y: 0 + type: tool + data: + provider_id: tealtiger + provider_type: plugin + tool_name: governance_scan + tool_parameters: + content: '{{start.user_input}}' + pii_detection: true + prompt_injection: true + content_moderation: true + budget: 5.0 + - id: llm_generation + position: + x: 600 + y: -100 + type: llm + data: + prompt: '{{start.user_input}}' + - id: end_blocked + position: + x: 600 + y: 100 + type: end + data: + outputs: + result: "Blocked by TealTiger policy." diff --git a/packages/dify-plugin-tealtiger/manifest.yaml b/packages/dify-plugin-tealtiger/manifest.yaml new file mode 100644 index 0000000..780ed35 --- /dev/null +++ b/packages/dify-plugin-tealtiger/manifest.yaml @@ -0,0 +1,5 @@ +version: 0.0.1 +name: tealtiger +author: TealTiger Team +description: TealTiger governance and policy enforcement integration. +type: tool diff --git a/packages/dify-plugin-tealtiger/provider/tealtiger.yaml b/packages/dify-plugin-tealtiger/provider/tealtiger.yaml new file mode 100644 index 0000000..434b2b4 --- /dev/null +++ b/packages/dify-plugin-tealtiger/provider/tealtiger.yaml @@ -0,0 +1,11 @@ +identity: + name: tealtiger + author: TealTiger Team + label: + en_US: TealTiger +credentials_for_provider: + api_key: + type: secret-input + required: true + label: + en_US: API Key diff --git a/packages/dify-plugin-tealtiger/requirements.txt b/packages/dify-plugin-tealtiger/requirements.txt new file mode 100644 index 0000000..e47f61c --- /dev/null +++ b/packages/dify-plugin-tealtiger/requirements.txt @@ -0,0 +1 @@ +tealtiger>=1.4.0 diff --git a/packages/dify-plugin-tealtiger/tools/governance_scan.py b/packages/dify-plugin-tealtiger/tools/governance_scan.py new file mode 100644 index 0000000..778fa50 --- /dev/null +++ b/packages/dify-plugin-tealtiger/tools/governance_scan.py @@ -0,0 +1,58 @@ +from dify_plugin import Tool +from typing import Any, Dict +import os +from tealtiger import TealGuard + +class TealTigerGovernanceTool(Tool): + def _invoke(self, tool_parameters: Dict[str, Any]) -> Dict[str, Any]: + api_key = self.runtime.credentials.get("api_key") + if not api_key: + return { + "error": "api_key is missing", + "decision": "DENY", + "reason": "Missing TealTiger API key" + } + + content = tool_parameters.get("content", "") + pii_detection = tool_parameters.get("pii_detection", True) + prompt_injection = tool_parameters.get("prompt_injection", True) + content_moderation = tool_parameters.get("content_moderation", True) + secret_detection = tool_parameters.get("secret_detection", True) + # Note: Budget is retrieved but not enforced by TealGuard as it is a local scan. + + # Initialize TealTiger client (TealGuard for deterministic scanning) + try: + # TealGuard SDK respects the API key via env var if needed by any remote stages + os.environ["TEALTIGER_API_KEY"] = api_key + + guard = TealGuard( + guardrails={ + "pre": { + "pii": pii_detection, + "injection": prompt_injection, + "content": content_moderation, + "secrets": secret_detection + } + } + ) + + # Evaluate content deterministically without incurring LLM cost + decision_obj = guard.evaluate_sync({"content": content}) + + return { + "decision": decision_obj.action, + "content_evaluated": content, + "security_info": { + "action": decision_obj.action, + "risk_score": getattr(decision_obj, "risk_score", 0.0), + "reason_codes": getattr(decision_obj, "reason_codes", []), + "short_circuited": getattr(decision_obj, "short_circuited", False), + "total_latency_ms": getattr(decision_obj, "total_latency_ms", 0.0) + } + } + except Exception as e: + return { + "error": str(e), + "decision": "DENY", + "reason": f"TealTiger evaluation failed: {str(e)}" + } diff --git a/packages/dify-plugin-tealtiger/tools/governance_scan.yaml b/packages/dify-plugin-tealtiger/tools/governance_scan.yaml new file mode 100644 index 0000000..564d732 --- /dev/null +++ b/packages/dify-plugin-tealtiger/tools/governance_scan.yaml @@ -0,0 +1,50 @@ +identity: + name: governance_scan + author: TealTiger Team + label: + en_US: TealTiger Governance Scan +description: + human: + en_US: Scans input text for PII, secrets, and policy violations. Returns an ALLOW or DENY decision with reason codes. + llm: A tool to scan text for PII, prompt injections, or policy violations. +parameters: + - name: content + type: string + required: true + label: + en_US: Input Content + human_description: + en_US: The content to scan + llm_description: The input text to evaluate. + - name: pii_detection + type: boolean + required: false + default: true + label: + en_US: Enable PII Detection + - name: prompt_injection + type: boolean + required: false + default: true + label: + en_US: Enable Prompt Injection Prevention + - name: content_moderation + type: boolean + required: false + default: true + label: + en_US: Enable Content Moderation + - name: secret_detection + type: boolean + required: false + default: true + label: + en_US: Enable Secret Detection + - name: budget + type: number + required: false + default: 0 + label: + en_US: Enforce Maximum Budget ($) + human_description: + en_US: Fails the evaluation if the budget is exceeded (0 means no limit).