agents-scope 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.
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # agent-scope
2
+
3
+ A security layer that ensures agents can only use the tools they're explicitly allowed to access.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun add agent-scope
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { createAgentScope } from "agent-scope";
15
+
16
+ const scope = createAgentScope({
17
+ agents: [
18
+ { id: "researcher", permissions: ["read_doc"] },
19
+ { id: "admin", permissions: ["read_doc", "admin_delete_user"] },
20
+ ],
21
+ });
22
+
23
+ // pass the tool and tool_id
24
+ const secureTool = scope.agent("researcher").secureTool(tool, "read_doc");
25
+ ```
26
+
27
+ **Any attempt by the research agent to execute `admin_delete_user` will be blocked.**
package/dist/core.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ interface AgentConfig {
2
+ id: string;
3
+ permissions: string[];
4
+ }
5
+ interface AgentScopeConfig {
6
+ agents: AgentConfig[];
7
+ }
8
+ export declare class UnknownAgentError extends Error {
9
+ constructor(agentId: string);
10
+ }
11
+ export declare class UnknownToolError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ export declare class PermissionDeniedError extends Error {
15
+ constructor(agentId: string, toolId: string);
16
+ }
17
+ export declare class ToolExecutionMethodNotFoundError extends Error {
18
+ constructor();
19
+ }
20
+ interface Tool {
21
+ name?: string;
22
+ id?: string;
23
+ invoke?: (...args: any[]) => any;
24
+ func?: (...args: any[]) => any;
25
+ execute?: (...args: any[]) => any;
26
+ [key: string]: any;
27
+ }
28
+ export declare function createAgentScope(config: AgentScopeConfig): {
29
+ agent(agentId: string): {
30
+ secureTool<T extends Tool>(tool: T, toolId?: string): T;
31
+ };
32
+ };
33
+ export declare const createAgentAuth: typeof createAgentScope;
34
+ export {};
@@ -0,0 +1 @@
1
+ export { createAgentScope, createAgentAuth, UnknownAgentError, UnknownToolError, PermissionDeniedError, ToolExecutionMethodNotFoundError, } from "./core";
package/dist/index.js ADDED
@@ -0,0 +1,111 @@
1
+ // core.ts
2
+ function validateAgentScopeConfig(config) {
3
+ if (!config || typeof config !== "object") {
4
+ throw new Error("AgentScope: config must be an object.");
5
+ }
6
+ if (!Array.isArray(config.agents)) {
7
+ throw new Error("AgentScope: `agents` must be an array.");
8
+ }
9
+ const seenAgentIds = new Set;
10
+ for (let i = 0;i < config.agents.length; i++) {
11
+ const agent = config.agents[i];
12
+ if (!agent || typeof agent !== "object") {
13
+ throw new Error(`AgentScope: agents[${i}] must be an object.`);
14
+ }
15
+ if (typeof agent.id !== "string" || agent.id.trim().length === 0) {
16
+ throw new Error(`AgentScope: agents[${i}].id must be a non-empty string.`);
17
+ }
18
+ if (seenAgentIds.has(agent.id)) {
19
+ throw new Error(`AgentScope: duplicate agent id '${agent.id}'.`);
20
+ }
21
+ seenAgentIds.add(agent.id);
22
+ if (!Array.isArray(agent.permissions)) {
23
+ throw new Error(`AgentScope: agents[${i}].permissions must be an array.`);
24
+ }
25
+ for (let j = 0;j < agent.permissions.length; j++) {
26
+ const permission = agent.permissions[j];
27
+ if (typeof permission !== "string" || permission.trim().length === 0) {
28
+ throw new Error(`AgentScope: agents[${i}].permissions[${j}] must be a non-empty string.`);
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ class UnknownAgentError extends Error {
35
+ constructor(agentId) {
36
+ super(`Agent with ID ${agentId} not found.`);
37
+ this.name = "UnknownAgentError";
38
+ }
39
+ }
40
+
41
+ class UnknownToolError extends Error {
42
+ constructor(message) {
43
+ super(message);
44
+ this.name = "UnknownToolError";
45
+ }
46
+ }
47
+
48
+ class PermissionDeniedError extends Error {
49
+ constructor(agentId, toolId) {
50
+ super(`Agent with ID ${agentId} has no tool permission with name ${toolId}`);
51
+ this.name = "PermissionDeniedError";
52
+ }
53
+ }
54
+
55
+ class ToolExecutionMethodNotFoundError extends Error {
56
+ constructor() {
57
+ super("AgentScope: Could not find an execution function (invoke/func/execute/_call) on tool.");
58
+ this.name = "ToolExecutionMethodNotFoundError";
59
+ }
60
+ }
61
+ function createAgentScope(config) {
62
+ validateAgentScopeConfig(config);
63
+ const knownToolIds = new Set(config.agents.flatMap((agent) => agent.permissions));
64
+ return {
65
+ agent(agentId) {
66
+ const currentAgent = config.agents.find((v) => v.id === agentId);
67
+ if (!currentAgent) {
68
+ throw new UnknownAgentError(agentId);
69
+ }
70
+ return {
71
+ secureTool(tool, toolId) {
72
+ const toolWithFallback = tool;
73
+ const method = typeof tool.invoke === "function" ? "invoke" : typeof tool.func === "function" ? "func" : typeof tool.execute === "function" ? "execute" : typeof toolWithFallback._call === "function" ? "_call" : null;
74
+ if (!method) {
75
+ throw new ToolExecutionMethodNotFoundError;
76
+ }
77
+ const resolvedToolId = toolId ?? tool.name ?? tool.id;
78
+ if (!resolvedToolId) {
79
+ throw new UnknownToolError("AgentScope: Missing tool id. Pass toolId explicitly or set tool.name/tool.id.");
80
+ }
81
+ if (!knownToolIds.has(resolvedToolId)) {
82
+ throw new UnknownToolError(`AgentScope: Unknown tool id '${resolvedToolId}' is denied by default.`);
83
+ }
84
+ const sourceTool = tool;
85
+ const executor = sourceTool[method];
86
+ const original = executor.bind(tool);
87
+ const wrappedTool = Object.create(Object.getPrototypeOf(tool));
88
+ Object.defineProperties(wrappedTool, Object.getOwnPropertyDescriptors(tool));
89
+ const mutableWrappedTool = wrappedTool;
90
+ mutableWrappedTool[method] = async (...args) => {
91
+ const isValidTool = currentAgent.permissions.includes(resolvedToolId);
92
+ if (!isValidTool) {
93
+ throw new PermissionDeniedError(agentId, resolvedToolId);
94
+ }
95
+ return original(...args);
96
+ };
97
+ return wrappedTool;
98
+ }
99
+ };
100
+ }
101
+ };
102
+ }
103
+ var createAgentAuth = createAgentScope;
104
+ export {
105
+ createAgentScope,
106
+ createAgentAuth,
107
+ UnknownToolError,
108
+ UnknownAgentError,
109
+ ToolExecutionMethodNotFoundError,
110
+ PermissionDeniedError
111
+ };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "agents-scope",
3
+ "version": "0.1.0",
4
+ "description": "Framework-agnostic tool authorization for AI agents.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Muhammad-Owais-Warsi/agent-scope.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/Muhammad-Owais-Warsi/agent-scope/issues"
13
+ },
14
+ "homepage": "https://github.com/Muhammad-Owais-Warsi/agent-scope#readme",
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "README.md"
27
+ ],
28
+ "scripts": {
29
+ "clean": "rm -rf dist",
30
+ "build:js": "bun build ./index.ts --outfile ./dist/index.js --format esm --target node",
31
+ "build:types": "bunx tsc -p tsconfig.build.json",
32
+ "build": "bun run clean && bun run build:js && bun run build:types",
33
+ "typecheck": "bunx tsc --noEmit"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "devDependencies": {
39
+ "@types/bun": "latest"
40
+ },
41
+ "peerDependencies": {
42
+ "typescript": "^5"
43
+ }
44
+ }