@dinpd/ai-agent-guard 0.1.0

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.
@@ -0,0 +1,95 @@
1
+ import policy from "./support-refund-policy.json" with { type: "json" };
2
+
3
+ import { createToolGate, type GuardCheck } from "../src/index.ts";
4
+
5
+ const gate = createToolGate({
6
+ policy,
7
+ now: () => new Date("2026-06-11T12:00:00Z"),
8
+ idGenerator: demoIds(),
9
+ });
10
+
11
+ const tools = {
12
+ "crm.read_customer": async (input: { customerId: string }) => ({
13
+ customerId: input.customerId,
14
+ caseId: "case-1042",
15
+ plan: "pro",
16
+ }),
17
+ "stripe.refund": async (input: { paymentId: string; amountUsd: number }) => ({
18
+ refundId: "re_123",
19
+ paymentId: input.paymentId,
20
+ amountUsd: input.amountUsd,
21
+ }),
22
+ };
23
+
24
+ await runTool(
25
+ "Allowed CRM read",
26
+ {
27
+ agentId: "support-agent",
28
+ userId: "user-17",
29
+ jobId: "case-gate",
30
+ tool: "crm.read_customer",
31
+ action: "read",
32
+ resource: "customer/cus_123",
33
+ dataFrom: "provider_crm",
34
+ dataTo: "agent_context",
35
+ dataClassification: ["customer_data"],
36
+ fieldSet: ["customer_id", "case_id", "plan"],
37
+ recordCount: 1,
38
+ },
39
+ () => tools["crm.read_customer"]({ customerId: "cus_123" }),
40
+ );
41
+
42
+ await runTool(
43
+ "Refund pauses for approval",
44
+ {
45
+ agentId: "support-agent",
46
+ userId: "user-17",
47
+ jobId: "case-gate",
48
+ tool: "stripe.refund",
49
+ action: "pay",
50
+ resource: "payment/pi_123",
51
+ amountUsd: 49,
52
+ idempotencyKey: "refund-case-gate-pi_123",
53
+ },
54
+ () => tools["stripe.refund"]({ paymentId: "pi_123", amountUsd: 49 }),
55
+ );
56
+
57
+ await runTool(
58
+ "Unknown tool is blocked",
59
+ {
60
+ agentId: "support-agent",
61
+ userId: "user-17",
62
+ jobId: "case-gate",
63
+ tool: "shell.exec",
64
+ action: "admin",
65
+ resource: "prod-host",
66
+ },
67
+ async () => ({ output: "this callback is never invoked" }),
68
+ );
69
+
70
+ async function runTool<TResult>(
71
+ label: string,
72
+ check: GuardCheck,
73
+ execute: () => Promise<TResult>,
74
+ ): Promise<void> {
75
+ const execution = await gate.run(check, execute);
76
+ console.log(
77
+ JSON.stringify(
78
+ {
79
+ label,
80
+ executed: execution.executed,
81
+ decision: execution.decision.type,
82
+ reasons: execution.decision.reasons,
83
+ challenge: execution.decision.challenge,
84
+ result: execution.executed ? execution.result : undefined,
85
+ },
86
+ null,
87
+ 2,
88
+ ),
89
+ );
90
+ }
91
+
92
+ function demoIds(): () => string {
93
+ let next = 1;
94
+ return () => `gate-demo-dec-${next++}`;
95
+ }
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@dinpd/ai-agent-guard",
3
+ "version": "0.1.0",
4
+ "description": "Runtime authorization guard for AI agent tool calls.",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "examples",
18
+ "policies",
19
+ "README.md"
20
+ ],
21
+ "sideEffects": false,
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/dinpd/AgentPass.git",
25
+ "directory": "packages/guard"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/dinpd/AgentPass/issues"
29
+ },
30
+ "homepage": "https://github.com/dinpd/AgentPass/tree/main/packages/guard#readme",
31
+ "keywords": [
32
+ "ai-agents",
33
+ "agent",
34
+ "guardrails",
35
+ "tool-calling",
36
+ "mcp",
37
+ "authorization",
38
+ "policy",
39
+ "pii",
40
+ "circuit-breaker"
41
+ ],
42
+ "engines": {
43
+ "node": ">=20"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc -p tsconfig.json",
50
+ "prepack": "npm run build",
51
+ "prepublishOnly": "npm test && npm run build",
52
+ "demo:quickstart": "node --import tsx examples/quickstart-agent-loop.ts",
53
+ "demo:circuit": "node --import tsx examples/circuit-breaker-demo.ts",
54
+ "demo:mcp": "node --import tsx examples/mcp-tool-call-demo.ts",
55
+ "demo": "node --import tsx examples/support-refund-demo.ts",
56
+ "demo:gate": "node --import tsx examples/tool-gate-demo.ts",
57
+ "demo:pii": "node --import tsx examples/pii-exfiltration-demo.ts",
58
+ "test": "node --test --import tsx tests/*.test.ts"
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "^25.9.1",
62
+ "tsx": "^4.20.6",
63
+ "typescript": "^5.9.3"
64
+ }
65
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "tools": {
3
+ "provider.crm.search_customer": {
4
+ "action": "read"
5
+ },
6
+ "provider.crm.update_customer": {
7
+ "action": "write",
8
+ "requiresApproval": true,
9
+ "allowedFields": ["customer_id", "case_id", "support_note", "plan"]
10
+ },
11
+ "provider.billing.issue_credit": {
12
+ "action": "pay",
13
+ "requiresApproval": true,
14
+ "maxAmountUsd": 100,
15
+ "requireIdempotencyKey": true,
16
+ "singleUse": true
17
+ },
18
+ "provider.email.send_external": {
19
+ "action": "send",
20
+ "requiresApprovalIfPii": true,
21
+ "allowedDomains": ["customer.example"],
22
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth"]
23
+ }
24
+ },
25
+ "flows": [
26
+ {
27
+ "from": "provider_crm",
28
+ "to": "agent_context",
29
+ "dataClassification": ["customer_data", "pii"],
30
+ "allowedFields": ["customer_id", "case_id", "plan"],
31
+ "maxRecords": 10
32
+ },
33
+ {
34
+ "from": "provider_crm",
35
+ "to": "external_email",
36
+ "destinationType": "external_email",
37
+ "dataClassification": ["customer_data", "pii"],
38
+ "requiresApproval": true,
39
+ "allowedDomains": ["customer.example"],
40
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth"]
41
+ }
42
+ ],
43
+ "budgets": {
44
+ "maxToolCallsPerJob": 15,
45
+ "maxSameToolCallsPerJob": 6,
46
+ "maxIdenticalToolCallsPerJob": 2,
47
+ "maxEstimatedCostUsdPerJob": 1
48
+ },
49
+ "defaultSensitiveDestinationDecision": "deny"
50
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "tools": {
3
+ "crm.read_customer": {
4
+ "action": "read"
5
+ },
6
+ "gmail.send": {
7
+ "action": "send",
8
+ "requiresApprovalIfPii": true,
9
+ "allowedDomains": ["customer.example"],
10
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
11
+ },
12
+ "webhook.post": {
13
+ "action": "send",
14
+ "requiresApprovalIfPii": true,
15
+ "allowedDomains": ["approved.partner.example"],
16
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
17
+ },
18
+ "llm.prompt": {
19
+ "action": "send",
20
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
21
+ },
22
+ "file.export": {
23
+ "action": "export",
24
+ "requiresApprovalIfPii": true,
25
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
26
+ },
27
+ "browser.fill_form": {
28
+ "action": "send",
29
+ "requiresApprovalIfPii": true,
30
+ "allowedDomains": ["customer.example"],
31
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
32
+ }
33
+ },
34
+ "flows": [
35
+ {
36
+ "from": "provider_crm",
37
+ "to": "agent_context",
38
+ "dataClassification": ["customer_data", "pii"],
39
+ "allowedFields": ["customer_id", "case_id", "plan", "renewal_date"],
40
+ "maxRecords": 10
41
+ },
42
+ {
43
+ "from": "provider_crm",
44
+ "to": "external_email",
45
+ "destinationType": "external_email",
46
+ "dataClassification": ["customer_data", "pii"],
47
+ "requiresApproval": true,
48
+ "allowedDomains": ["customer.example"],
49
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
50
+ },
51
+ {
52
+ "from": "provider_crm",
53
+ "to": "model_provider",
54
+ "destinationType": "model_provider",
55
+ "dataClassification": ["pii"],
56
+ "decision": "deny",
57
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
58
+ },
59
+ {
60
+ "from": "provider_crm",
61
+ "to": "file_export",
62
+ "destinationType": "file_export",
63
+ "dataClassification": ["customer_data", "pii"],
64
+ "requiresApproval": true,
65
+ "maxRecords": 50,
66
+ "blockedFields": ["ssn", "access_token", "payment_method", "full_date_of_birth", "health_record_id"]
67
+ },
68
+ {
69
+ "from": "secrets_manager",
70
+ "to": "model_provider",
71
+ "decision": "deny"
72
+ }
73
+ ],
74
+ "defaultSensitiveDestinationDecision": "deny"
75
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "tools": {
3
+ "stripe.refund": {
4
+ "action": "pay",
5
+ "requiresApproval": true,
6
+ "maxAmountUsd": 100,
7
+ "requireIdempotencyKey": true,
8
+ "singleUse": true
9
+ },
10
+ "crm.read_customer": {
11
+ "action": "read"
12
+ },
13
+ "crm.update_customer": {
14
+ "action": "write",
15
+ "requiresApproval": true,
16
+ "allowedFields": ["case_id", "plan", "renewal_date", "support_note"]
17
+ }
18
+ },
19
+ "budgets": {
20
+ "maxToolCallsPerJob": 10,
21
+ "maxSameToolCallsPerJob": 4,
22
+ "maxIdenticalToolCallsPerJob": 2,
23
+ "maxRetriesPerTool": 1,
24
+ "maxEstimatedCostUsdPerJob": 1
25
+ }
26
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "tools": {
3
+ "browser.open": {
4
+ "action": "read",
5
+ "allowedDomains": ["docs.example", "github.com"]
6
+ },
7
+ "browser.fill_form": {
8
+ "action": "send",
9
+ "requiresApprovalIfPii": true,
10
+ "allowedDomains": ["customer.example"],
11
+ "blockedFields": ["password", "access_token", "api_key", "ssn", "payment_method"]
12
+ },
13
+ "shell.exec": {
14
+ "action": "admin",
15
+ "requiresApproval": true,
16
+ "blockedFields": ["api_key", "access_token", "password", "private_key"]
17
+ },
18
+ "file.write": {
19
+ "action": "write",
20
+ "requiresApproval": true,
21
+ "blockedFields": ["api_key", "access_token", "password", "private_key"]
22
+ }
23
+ },
24
+ "flows": [
25
+ {
26
+ "from": "secrets_manager",
27
+ "to": "model_provider",
28
+ "decision": "deny"
29
+ },
30
+ {
31
+ "from": "local_files",
32
+ "to": "external_email",
33
+ "destinationType": "external_email",
34
+ "dataClassification": ["secret", "regulated"],
35
+ "decision": "deny"
36
+ },
37
+ {
38
+ "from": "local_files",
39
+ "to": "browser_form",
40
+ "destinationType": "browser_form",
41
+ "dataClassification": ["pii", "secret"],
42
+ "requiresApproval": true,
43
+ "allowedDomains": ["customer.example"],
44
+ "blockedFields": ["password", "access_token", "api_key", "ssn", "payment_method"]
45
+ }
46
+ ],
47
+ "budgets": {
48
+ "challengeAfterRuntimeMsPerJob": 120000,
49
+ "maxRuntimeMsPerJob": 300000,
50
+ "maxToolCallsPerJob": 20,
51
+ "maxSameToolCallsPerJob": 8,
52
+ "maxIdenticalToolCallsPerJob": 2
53
+ },
54
+ "defaultSensitiveDestinationDecision": "deny"
55
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "tools": {
3
+ "web.search": {
4
+ "action": "read"
5
+ },
6
+ "llm.complete": {
7
+ "action": "send"
8
+ },
9
+ "browser.open": {
10
+ "action": "read"
11
+ }
12
+ },
13
+ "budgets": {
14
+ "challengeAfterToolCallsPerJob": 8,
15
+ "challengeAfterTokensPerJob": 12000,
16
+ "challengeAfterEstimatedCostUsdPerJob": 0.75,
17
+ "maxToolCallsPerJob": 15,
18
+ "maxSameToolCallsPerJob": 6,
19
+ "maxIdenticalToolCallsPerJob": 2,
20
+ "maxRetriesPerTool": 2,
21
+ "maxTokensPerJob": 20000,
22
+ "maxEstimatedCostUsdPerJob": 1
23
+ }
24
+ }