@agent-action-firewall/sdk
v1.0.0
Published
Official TypeScript SDK for Agent Action Firewall - AI agent security platform
Maintainers
Readme
Agent Action Firewall TypeScript SDK
Official TypeScript SDK for the Agent Action Firewall - a security layer for AI agents.
Installation
npm install @agent-action-firewall/sdk
# or
pnpm add @agent-action-firewall/sdk
# or
yarn add @agent-action-firewall/sdkQuick Start
import { AgentFirewallClient } from '@agent-action-firewall/sdk';
const client = new AgentFirewallClient({
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: process.env.AGENT_FIREWALL_API_KEY!,
agentId: 'my-agent',
});
// Submit an action for policy evaluation
const response = await client.submitAction({
tool: 'http_proxy',
operation: 'POST',
params: {
url: 'https://api.example.com/data',
body: { key: 'value' },
},
});
console.log('Action status:', response.status);Usage
Submit an Action
const response = await client.submitAction({
tool: 'http_proxy',
operation: 'POST',
params: {
url: 'https://api.example.com/data',
body: { key: 'value' },
},
// Optional: prevent duplicate submissions
idempotencyKey: 'unique-request-id',
});
switch (response.status) {
case 'allowed':
// Action is allowed, execute it
console.log('Action allowed');
break;
case 'denied':
// Action was denied by policy
console.log('Denied:', response.decision?.reason);
break;
case 'pending_approval':
// Requires human approval
console.log('Waiting for approval:', response.approvalId);
break;
}Get Action Status
const detail = await client.getAction(actionId);
console.log('Status:', detail.status);
console.log('Decision:', detail.decision);
console.log('Approval:', detail.approval);Wait for Approval
// Wait up to 5 minutes for approval
const finalStatus = await client.waitForApproval(actionId, {
timeout: 300000,
interval: 2000, // Poll every 2 seconds
onStatusChange: (status) => {
console.log('Status update:', status.status);
},
});
console.log('Final status:', finalStatus.status);Submit and Wait
Convenience method that submits an action and waits for completion:
const result = await client.submitAndWait({
tool: 'jira',
operation: 'create_ticket',
params: {
project: 'PROJ',
summary: 'New ticket',
description: 'Created by AI agent',
},
});
if (result.status === 'succeeded') {
console.log('Ticket created:', result.execution?.result);
}Configuration Options
const client = new AgentFirewallClient({
// Required
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: 'your-api-key',
agentId: 'your-agent-id',
// Optional
timeout: 30000, // Request timeout in ms (default: 30000)
debug: false, // Enable debug logging
});Error Handling
import { AgentFirewallError } from '@agent-action-firewall/sdk';
try {
await client.submitAction({ ... });
} catch (error) {
if (error instanceof AgentFirewallError) {
console.error('Code:', error.code);
console.error('Message:', error.message);
console.error('Status:', error.statusCode);
console.error('Details:', error.details);
}
}Error Codes
CONFIG_ERROR- Invalid configurationNETWORK_ERROR- Network connectivity issueTIMEOUT_ERROR- Request or polling timeoutAPI_ERROR- API returned an error response
Types
The SDK exports TypeScript types for all request and response objects:
import type {
AgentFirewallConfig,
ActionRequest,
ActionResponse,
ActionDetail,
ActionDecision,
ApprovalSummary,
ExecutionSummary,
PollOptions,
} from '@agent-action-firewall/sdk';Integration Examples
OpenAI Function Calling
Wrap OpenAI function calls with firewall governance:
import OpenAI from 'openai';
import { AgentFirewallClient } from '@agent-action-firewall/sdk';
const openai = new OpenAI();
const firewall = new AgentFirewallClient({
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: process.env.AGENT_FIREWALL_API_KEY!,
agentId: 'openai-assistant',
});
// Define a governed function
async function executeFunction(name: string, args: Record<string, unknown>) {
// Check with firewall before executing
const response = await firewall.submitAndWait({
tool: name,
operation: 'execute',
params: args,
});
if (response.status === 'denied') {
throw new Error(`Action denied: ${response.decision?.reason}`);
}
// Execute the actual function
return await actualFunctionExecution(name, args);
}
// Use with OpenAI
const completion = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Create a Jira ticket for the bug' }],
tools: [
{
type: 'function',
function: {
name: 'create_jira_ticket',
parameters: { /* ... */ },
},
},
],
});
// When OpenAI wants to call a function
for (const call of completion.choices[0].message.tool_calls || []) {
const result = await executeFunction(
call.function.name,
JSON.parse(call.function.arguments)
);
}Anthropic Claude Tool Use
Integrate with Claude's tool use capabilities:
import Anthropic from '@anthropic-ai/sdk';
import { AgentFirewallClient } from '@agent-action-firewall/sdk';
const anthropic = new Anthropic();
const firewall = new AgentFirewallClient({
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: process.env.AGENT_FIREWALL_API_KEY!,
agentId: 'claude-assistant',
});
async function handleToolUse(toolName: string, toolInput: Record<string, unknown>) {
// Submit to firewall
const response = await firewall.submitAndWait({
tool: toolName,
operation: 'execute',
params: toolInput,
metadata: {
source: 'claude',
model: 'claude-3-opus',
},
});
if (response.status !== 'succeeded') {
return { error: `Action ${response.status}: ${response.decision?.reason}` };
}
return response.execution?.result;
}
const message = await anthropic.messages.create({
model: 'claude-3-opus-20240229',
max_tokens: 1024,
tools: [
{
name: 'send_email',
description: 'Send an email to a recipient',
input_schema: {
type: 'object',
properties: {
to: { type: 'string' },
subject: { type: 'string' },
body: { type: 'string' },
},
required: ['to', 'subject', 'body'],
},
},
],
messages: [{ role: 'user', content: 'Send an email to [email protected]' }],
});
// Process tool use blocks
for (const block of message.content) {
if (block.type === 'tool_use') {
const result = await handleToolUse(block.name, block.input);
// Continue conversation with result...
}
}Vercel AI SDK
Use with the Vercel AI SDK for streaming responses:
import { openai } from '@ai-sdk/openai';
import { streamText, tool } from 'ai';
import { z } from 'zod';
import { AgentFirewallClient } from '@agent-action-firewall/sdk';
const firewall = new AgentFirewallClient({
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: process.env.AGENT_FIREWALL_API_KEY!,
agentId: 'vercel-ai-agent',
});
const result = await streamText({
model: openai('gpt-4-turbo'),
tools: {
createTicket: tool({
description: 'Create a support ticket',
parameters: z.object({
title: z.string(),
description: z.string(),
priority: z.enum(['low', 'medium', 'high']),
}),
execute: async ({ title, description, priority }) => {
// Firewall check
const response = await firewall.submitAndWait({
tool: 'ticketing',
operation: 'create',
params: { title, description, priority },
});
if (response.status === 'denied') {
return { error: response.decision?.reason };
}
return { ticketId: response.execution?.result?.id };
},
}),
},
messages: [{ role: 'user', content: 'Create a high priority ticket for the outage' }],
});LangChain.js Integration
Wrap LangChain tools with firewall governance:
import { ChatOpenAI } from '@langchain/openai';
import { DynamicStructuredTool } from '@langchain/core/tools';
import { AgentExecutor, createOpenAIToolsAgent } from 'langchain/agents';
import { AgentFirewallClient } from '@agent-action-firewall/sdk';
import { z } from 'zod';
const firewall = new AgentFirewallClient({
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: process.env.AGENT_FIREWALL_API_KEY!,
agentId: 'langchain-agent',
});
// Create a governed tool
const governedSearchTool = new DynamicStructuredTool({
name: 'web_search',
description: 'Search the web for information',
schema: z.object({
query: z.string().describe('The search query'),
}),
func: async ({ query }) => {
// Check with firewall first
const response = await firewall.submitAndWait({
tool: 'web_search',
operation: 'search',
params: { query },
});
if (response.status === 'denied') {
throw new Error(`Search denied: ${response.decision?.reason}`);
}
// Execute actual search
return await performWebSearch(query);
},
});
const llm = new ChatOpenAI({ model: 'gpt-4' });
const agent = await createOpenAIToolsAgent({
llm,
tools: [governedSearchTool],
prompt: /* your prompt */,
});Express.js Middleware
Create middleware for API routes that require firewall approval:
import express from 'express';
import { AgentFirewallClient } from '@agent-action-firewall/sdk';
const app = express();
const firewall = new AgentFirewallClient({
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: process.env.AGENT_FIREWALL_API_KEY!,
agentId: 'api-gateway',
});
// Middleware to check firewall for all agent actions
const firewallMiddleware = (toolName: string) => {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
try {
const response = await firewall.submitAction({
tool: toolName,
operation: req.method,
params: {
path: req.path,
body: req.body,
query: req.query,
},
metadata: {
ip: req.ip,
userAgent: req.get('user-agent'),
},
});
if (response.status === 'denied') {
return res.status(403).json({
error: 'Action denied by policy',
reason: response.decision?.reason,
riskLevel: response.decision?.riskLevel,
});
}
if (response.status === 'pending_approval') {
return res.status(202).json({
message: 'Action requires approval',
approvalId: response.approvalId,
actionId: response.id,
});
}
// Attach action info to request for logging
req.firewallAction = response;
next();
} catch (error) {
next(error);
}
};
};
// Use on routes
app.post('/api/agents/:agentId/execute',
firewallMiddleware('agent_execution'),
async (req, res) => {
// Action was approved, proceed with execution
const result = await executeAgentAction(req.body);
res.json(result);
}
);Next.js API Route
Protect Next.js API routes with firewall checks:
// app/api/agent/action/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { AgentFirewallClient } from '@agent-action-firewall/sdk';
const firewall = new AgentFirewallClient({
baseUrl: 'https://api.agentactionfirewall.com',
apiKey: process.env.AGENT_FIREWALL_API_KEY!,
agentId: 'nextjs-agent',
});
export async function POST(request: NextRequest) {
const body = await request.json();
// Submit to firewall
const response = await firewall.submitAndWait({
tool: body.tool,
operation: body.operation,
params: body.params,
});
if (response.status === 'denied') {
return NextResponse.json(
{ error: 'Denied', reason: response.decision?.reason },
{ status: 403 }
);
}
if (response.status === 'succeeded') {
return NextResponse.json({
success: true,
result: response.execution?.result,
});
}
return NextResponse.json(
{ error: 'Action failed', status: response.status },
{ status: 400 }
);
}License
MIT
