agentrein 1.0.8 → 1.0.9
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 +71 -0
- package/dist/cjs/agentreinClient.d.ts +64 -0
- package/dist/cjs/agentreinClient.js +93 -0
- package/dist/cjs/errors.d.ts +12 -0
- package/dist/cjs/errors.js +27 -0
- package/dist/esm/agentreinClient.js +90 -0
- package/dist/esm/errors.js +21 -0
- package/package.json +14 -4
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# AgentRein SDK - Node.js Client
|
|
2
|
+
|
|
3
|
+
**AgentRein** is an AI Agent Reliability Platform that provides automatic rollback, approval gates, and intent verification for AI workflows. This SDK allows you to easily integrate AgentRein into your Node.js applications.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📦 Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install agentrein
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 🚀 Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { AgentRein } from 'agentrein'
|
|
17
|
+
|
|
18
|
+
const agentrein = new AgentRein({
|
|
19
|
+
apiKey: process.env.AGENTREIN_API_KEY, // Your Organization API Key
|
|
20
|
+
intentVerification: true, // Enable LLM intent check
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
async function runAgent() {
|
|
24
|
+
// 1. Create a session with a clear intent
|
|
25
|
+
const session = await agentrein.newSession({
|
|
26
|
+
agentId: 'support-agent-01',
|
|
27
|
+
intent: 'Refund customer cus_123 for order ord_456'
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// 2. Wrap your external API calls
|
|
32
|
+
const result = await agentrein.call(
|
|
33
|
+
stripe.refunds.create, // The function to execute
|
|
34
|
+
session, // The current session
|
|
35
|
+
{
|
|
36
|
+
type: 'http-delete',
|
|
37
|
+
url: 'https://api.stripe.com/v1/refunds/re_123'
|
|
38
|
+
}, // Undo configuration (if rollback is needed)
|
|
39
|
+
{ charge: 'ch_789' } // Original function arguments
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
console.log('Action executed safely:', result)
|
|
43
|
+
} catch (error) {
|
|
44
|
+
// 3. AgentRein automatically triggers rollback on failure
|
|
45
|
+
console.error('Action failed, rolling back previous steps...', error)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 🧠 Key Concepts
|
|
51
|
+
|
|
52
|
+
### Sessions
|
|
53
|
+
A `Session` groups multiple actions together. If any action in the session fails, AgentRein will attempt to roll back all previous successful actions in that session in reverse order.
|
|
54
|
+
|
|
55
|
+
### Intent Verification
|
|
56
|
+
By providing an `intent` when creating a session, AgentRein uses an LLM to verify that each subsequent action aligns with the user's original goal. If "drift" is detected, the action can be flagged or blocked.
|
|
57
|
+
|
|
58
|
+
### Approval Gates
|
|
59
|
+
You can configure rules in the [AgentRein Dashboard](https://agentrein.com/sessions) to require human approval for high-risk actions before they are executed.
|
|
60
|
+
|
|
61
|
+
## 🛠️ Configuration
|
|
62
|
+
|
|
63
|
+
| Option | Type | Description |
|
|
64
|
+
| :--- | :--- | :--- |
|
|
65
|
+
| `apiKey` | `string` | **Required**. Your organization's API key. |
|
|
66
|
+
| `baseUrl` | `string` | Optional. Defaults to `https://api.agentrein.com`. |
|
|
67
|
+
| `intentVerification` | `boolean` | Optional. Enable/disable LLM drift detection. |
|
|
68
|
+
|
|
69
|
+
## 📄 License
|
|
70
|
+
|
|
71
|
+
MIT
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { AgentReinUnavailableError } from './errors';
|
|
2
|
+
export interface AgentReinOptions {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
serverUrl?: string;
|
|
5
|
+
failureMode?: 'open' | 'closed';
|
|
6
|
+
}
|
|
7
|
+
export interface SessionOptions {
|
|
8
|
+
agentId?: string;
|
|
9
|
+
intent?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface UndoConfig {
|
|
12
|
+
type: 'slack-correction' | 'http-delete' | 'none';
|
|
13
|
+
url?: string;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
body?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface Session {
|
|
18
|
+
id: string;
|
|
19
|
+
organizationId: string;
|
|
20
|
+
agentId: string;
|
|
21
|
+
intent: string | null;
|
|
22
|
+
status: string;
|
|
23
|
+
startedAt: string;
|
|
24
|
+
endedAt: string | null;
|
|
25
|
+
}
|
|
26
|
+
export { AgentReinUnavailableError };
|
|
27
|
+
export declare class AgentRein {
|
|
28
|
+
private readonly serverUrl;
|
|
29
|
+
private readonly apiKey;
|
|
30
|
+
private readonly failureMode;
|
|
31
|
+
private token;
|
|
32
|
+
constructor(options: AgentReinOptions);
|
|
33
|
+
/**
|
|
34
|
+
* Obtain a JWT token from the AgentRein server using the API key.
|
|
35
|
+
* Caches the token for subsequent requests.
|
|
36
|
+
*/
|
|
37
|
+
private getToken;
|
|
38
|
+
/**
|
|
39
|
+
* Build authorization headers for server requests.
|
|
40
|
+
*/
|
|
41
|
+
private authHeaders;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new agent session on the AgentRein server.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Session options (agentId + optional intent).
|
|
46
|
+
* Can also pass a plain string for backward compat (agentId).
|
|
47
|
+
* If omitted, a random agentId is generated.
|
|
48
|
+
*/
|
|
49
|
+
newSession(options?: SessionOptions | string): Promise<Session>;
|
|
50
|
+
/**
|
|
51
|
+
* Execute an API call under AgentRein's protection.
|
|
52
|
+
*
|
|
53
|
+
* 1. Calls fn(...args)
|
|
54
|
+
* 2. Logs the action to the AgentRein server (async, non-blocking)
|
|
55
|
+
* 3. On failure, triggers server-side rollback
|
|
56
|
+
*
|
|
57
|
+
* @param fn - The function to execute
|
|
58
|
+
* @param session - The active AgentRein session
|
|
59
|
+
* @param args - Arguments forwarded to fn
|
|
60
|
+
*/
|
|
61
|
+
call<T>(fn: Function, session: Session, ...args: any[]): Promise<T>;
|
|
62
|
+
call<T>(fn: Function, session: Session, undoConfig: UndoConfig, ...args: any[]): Promise<T>;
|
|
63
|
+
}
|
|
64
|
+
export default AgentRein;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentRein = exports.AgentReinUnavailableError = void 0;
|
|
4
|
+
const axios_1 = require("axios");
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
Object.defineProperty(exports, "AgentReinUnavailableError", { enumerable: true, get: function () { return errors_1.AgentReinUnavailableError; } });
|
|
7
|
+
// ─── AgentRein Client ─────────────────────────────────────
|
|
8
|
+
class AgentRein {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.token = null;
|
|
11
|
+
this.serverUrl = options.serverUrl || 'https://api.agentrein.com';
|
|
12
|
+
this.apiKey = options.apiKey;
|
|
13
|
+
this.failureMode = options.failureMode ?? 'open';
|
|
14
|
+
}
|
|
15
|
+
// ── Authentication ──────────────────────────────────
|
|
16
|
+
/**
|
|
17
|
+
* Obtain a JWT token from the AgentRein server using the API key.
|
|
18
|
+
* Caches the token for subsequent requests.
|
|
19
|
+
*/
|
|
20
|
+
async getToken() {
|
|
21
|
+
if (this.token)
|
|
22
|
+
return this.token;
|
|
23
|
+
try {
|
|
24
|
+
const res = await axios_1.default.post(`${this.serverUrl}/auth/token`, {
|
|
25
|
+
apiKey: this.apiKey,
|
|
26
|
+
});
|
|
27
|
+
this.token = res.data.data.token;
|
|
28
|
+
return this.token;
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
throw new errors_1.AgentReinUnavailableError(`Failed to authenticate with AgentRein server: ${err instanceof Error ? err.message : String(err)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build authorization headers for server requests.
|
|
36
|
+
*/
|
|
37
|
+
async authHeaders() {
|
|
38
|
+
const token = await this.getToken();
|
|
39
|
+
return { Authorization: `Bearer ${token}` };
|
|
40
|
+
}
|
|
41
|
+
// ── newSession ───────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Create a new agent session on the AgentRein server.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Session options (agentId + optional intent).
|
|
46
|
+
* Can also pass a plain string for backward compat (agentId).
|
|
47
|
+
* If omitted, a random agentId is generated.
|
|
48
|
+
*/
|
|
49
|
+
async newSession(options) {
|
|
50
|
+
const resolved = typeof options === 'string'
|
|
51
|
+
? { agentId: options, intent: undefined }
|
|
52
|
+
: options ?? {};
|
|
53
|
+
const agentId = resolved.agentId ?? crypto.randomUUID();
|
|
54
|
+
const intent = resolved.intent;
|
|
55
|
+
const headers = await this.authHeaders();
|
|
56
|
+
const res = await axios_1.default.post(`${this.serverUrl}/sessions`, { agentId, intent }, { headers });
|
|
57
|
+
return res.data.data;
|
|
58
|
+
}
|
|
59
|
+
async call(fn, session, ...args) {
|
|
60
|
+
// Detect if first extra arg is an UndoConfig object
|
|
61
|
+
let undoConfig;
|
|
62
|
+
let callArgs = args;
|
|
63
|
+
if (args.length > 0 &&
|
|
64
|
+
args[0] &&
|
|
65
|
+
typeof args[0] === 'object' &&
|
|
66
|
+
'type' in args[0] &&
|
|
67
|
+
['slack-correction', 'http-delete', 'none'].includes(args[0].type)) {
|
|
68
|
+
undoConfig = args[0];
|
|
69
|
+
callArgs = args.slice(1);
|
|
70
|
+
}
|
|
71
|
+
const headers = await this.authHeaders();
|
|
72
|
+
try {
|
|
73
|
+
const result = await fn(...callArgs);
|
|
74
|
+
// Log action to server (fire-and-forget)
|
|
75
|
+
axios_1.default.post(`${this.serverUrl}/sessions/${session.id}/actions`, {
|
|
76
|
+
apiName: fn.name || 'anonymous',
|
|
77
|
+
operationType: 'CREATE',
|
|
78
|
+
payload: callArgs[0] ?? {},
|
|
79
|
+
response: result,
|
|
80
|
+
status: 'SUCCESS',
|
|
81
|
+
undoConfig,
|
|
82
|
+
}, { headers }).catch(() => { });
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
// Trigger server-side rollback
|
|
87
|
+
await axios_1.default.post(`${this.serverUrl}/sessions/${session.id}/rollback`, {}, { headers }).catch(() => { });
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.AgentRein = AgentRein;
|
|
93
|
+
exports.default = AgentRein;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom errors for the AgentRein SDK.
|
|
3
|
+
*/
|
|
4
|
+
export declare class AgentReinUnavailableError extends Error {
|
|
5
|
+
constructor(message?: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class ApprovalRejectedError extends Error {
|
|
8
|
+
constructor(apiName: string, reason?: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class ApprovalTimeoutError extends Error {
|
|
11
|
+
constructor(apiName: string, timeoutMinutes: number);
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Custom errors for the AgentRein SDK.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ApprovalTimeoutError = exports.ApprovalRejectedError = exports.AgentReinUnavailableError = void 0;
|
|
7
|
+
class AgentReinUnavailableError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message ?? 'AgentRein safety layer is unavailable');
|
|
10
|
+
this.name = 'AgentReinUnavailableError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.AgentReinUnavailableError = AgentReinUnavailableError;
|
|
14
|
+
class ApprovalRejectedError extends Error {
|
|
15
|
+
constructor(apiName, reason) {
|
|
16
|
+
super(`Action "${apiName}" was rejected by a human reviewer${reason ? `: ${reason}` : ''}`);
|
|
17
|
+
this.name = 'ApprovalRejectedError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.ApprovalRejectedError = ApprovalRejectedError;
|
|
21
|
+
class ApprovalTimeoutError extends Error {
|
|
22
|
+
constructor(apiName, timeoutMinutes) {
|
|
23
|
+
super(`Action "${apiName}" was not approved within ${timeoutMinutes} minutes — auto-rejected`);
|
|
24
|
+
this.name = 'ApprovalTimeoutError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.ApprovalTimeoutError = ApprovalTimeoutError;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { AgentReinUnavailableError } from './errors';
|
|
3
|
+
// Re-export errors for consumer convenience
|
|
4
|
+
export { AgentReinUnavailableError };
|
|
5
|
+
// ─── AgentRein Client ─────────────────────────────────────
|
|
6
|
+
export class AgentRein {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.token = null;
|
|
9
|
+
this.serverUrl = options.serverUrl || 'https://api.agentrein.com';
|
|
10
|
+
this.apiKey = options.apiKey;
|
|
11
|
+
this.failureMode = options.failureMode ?? 'open';
|
|
12
|
+
}
|
|
13
|
+
// ── Authentication ──────────────────────────────────
|
|
14
|
+
/**
|
|
15
|
+
* Obtain a JWT token from the AgentRein server using the API key.
|
|
16
|
+
* Caches the token for subsequent requests.
|
|
17
|
+
*/
|
|
18
|
+
async getToken() {
|
|
19
|
+
if (this.token)
|
|
20
|
+
return this.token;
|
|
21
|
+
try {
|
|
22
|
+
const res = await axios.post(`${this.serverUrl}/auth/token`, {
|
|
23
|
+
apiKey: this.apiKey,
|
|
24
|
+
});
|
|
25
|
+
this.token = res.data.data.token;
|
|
26
|
+
return this.token;
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
throw new AgentReinUnavailableError(`Failed to authenticate with AgentRein server: ${err instanceof Error ? err.message : String(err)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build authorization headers for server requests.
|
|
34
|
+
*/
|
|
35
|
+
async authHeaders() {
|
|
36
|
+
const token = await this.getToken();
|
|
37
|
+
return { Authorization: `Bearer ${token}` };
|
|
38
|
+
}
|
|
39
|
+
// ── newSession ───────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Create a new agent session on the AgentRein server.
|
|
42
|
+
*
|
|
43
|
+
* @param options - Session options (agentId + optional intent).
|
|
44
|
+
* Can also pass a plain string for backward compat (agentId).
|
|
45
|
+
* If omitted, a random agentId is generated.
|
|
46
|
+
*/
|
|
47
|
+
async newSession(options) {
|
|
48
|
+
const resolved = typeof options === 'string'
|
|
49
|
+
? { agentId: options, intent: undefined }
|
|
50
|
+
: options ?? {};
|
|
51
|
+
const agentId = resolved.agentId ?? crypto.randomUUID();
|
|
52
|
+
const intent = resolved.intent;
|
|
53
|
+
const headers = await this.authHeaders();
|
|
54
|
+
const res = await axios.post(`${this.serverUrl}/sessions`, { agentId, intent }, { headers });
|
|
55
|
+
return res.data.data;
|
|
56
|
+
}
|
|
57
|
+
async call(fn, session, ...args) {
|
|
58
|
+
// Detect if first extra arg is an UndoConfig object
|
|
59
|
+
let undoConfig;
|
|
60
|
+
let callArgs = args;
|
|
61
|
+
if (args.length > 0 &&
|
|
62
|
+
args[0] &&
|
|
63
|
+
typeof args[0] === 'object' &&
|
|
64
|
+
'type' in args[0] &&
|
|
65
|
+
['slack-correction', 'http-delete', 'none'].includes(args[0].type)) {
|
|
66
|
+
undoConfig = args[0];
|
|
67
|
+
callArgs = args.slice(1);
|
|
68
|
+
}
|
|
69
|
+
const headers = await this.authHeaders();
|
|
70
|
+
try {
|
|
71
|
+
const result = await fn(...callArgs);
|
|
72
|
+
// Log action to server (fire-and-forget)
|
|
73
|
+
axios.post(`${this.serverUrl}/sessions/${session.id}/actions`, {
|
|
74
|
+
apiName: fn.name || 'anonymous',
|
|
75
|
+
operationType: 'CREATE',
|
|
76
|
+
payload: callArgs[0] ?? {},
|
|
77
|
+
response: result,
|
|
78
|
+
status: 'SUCCESS',
|
|
79
|
+
undoConfig,
|
|
80
|
+
}, { headers }).catch(() => { });
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
// Trigger server-side rollback
|
|
85
|
+
await axios.post(`${this.serverUrl}/sessions/${session.id}/rollback`, {}, { headers }).catch(() => { });
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export default AgentRein;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom errors for the AgentRein SDK.
|
|
3
|
+
*/
|
|
4
|
+
export class AgentReinUnavailableError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message ?? 'AgentRein safety layer is unavailable');
|
|
7
|
+
this.name = 'AgentReinUnavailableError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ApprovalRejectedError extends Error {
|
|
11
|
+
constructor(apiName, reason) {
|
|
12
|
+
super(`Action "${apiName}" was rejected by a human reviewer${reason ? `: ${reason}` : ''}`);
|
|
13
|
+
this.name = 'ApprovalRejectedError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class ApprovalTimeoutError extends Error {
|
|
17
|
+
constructor(apiName, timeoutMinutes) {
|
|
18
|
+
super(`Action "${apiName}" was not approved within ${timeoutMinutes} minutes — auto-rejected`);
|
|
19
|
+
this.name = 'ApprovalTimeoutError';
|
|
20
|
+
}
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentrein",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"main": "dist/agentreinClient.js",
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.9",
|
|
4
|
+
"main": "./dist/cjs/agentreinClient.js",
|
|
5
|
+
"module": "./dist/esm/agentreinClient.js",
|
|
6
|
+
"types": "./dist/cjs/agentreinClient.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/esm/agentreinClient.js",
|
|
10
|
+
"require": "./dist/cjs/agentreinClient.js",
|
|
11
|
+
"types": "./dist/cjs/agentreinClient.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
6
14
|
"files": [
|
|
7
15
|
"dist/",
|
|
8
16
|
"README.md"
|
|
9
17
|
],
|
|
10
18
|
"scripts": {
|
|
11
|
-
"build": "
|
|
19
|
+
"build": "npm run build:cjs && npm run build:esm",
|
|
20
|
+
"build:cjs": "tsc --project tsconfig.cjs.json",
|
|
21
|
+
"build:esm": "tsc --project tsconfig.esm.json",
|
|
12
22
|
"prepublishOnly": "npm run build"
|
|
13
23
|
},
|
|
14
24
|
"dependencies": {
|