Custom Agents

Build custom agent logic, register custom tools, integrate with external APIs, and deploy in VPC private subnets.

Custom Agents let you build your own agent logic, register custom tools, and integrate with external APIs. Deploy them in VPC private subnets for secure access to internal services. Use custom agents when built-in RAG, LLM, or workflow agents don’t fit your use case.

Building Custom Agent Logic

Custom agents run your code. You define:

  1. Input schema — What the agent accepts
  2. Processing logic — How it processes input (calls to LLMs, tools, APIs)
  3. Output schema — What it returns

Agent Interface

interface CustomAgent {
  name: string;
  version: string;
  inputSchema: JSONSchema;
  outputSchema: JSONSchema;
  execute(input: Record<string, unknown>): Promise<Record<string, unknown>>;
}

Example: Custom Routing Agent

export const routingAgent: CustomAgent = {
  name: "support-router",
  version: "1.0.0",
  inputSchema: {
    type: "object",
    properties: {
      message: { type: "string" },
      customerTier: { type: "string", enum: ["free", "pro", "enterprise"] }
    },
    required: ["message"]
  },
  outputSchema: {
    type: "object",
    properties: {
      route: { type: "string" },
      priority: { type: "number" }
    }
  },
  async execute(input) {
    const { message, customerTier } = input;
    // Call internal API, LLM, or custom logic
    const route = await callInternalRoutingAPI(message, customerTier);
    return { route: route.destination, priority: route.priority };
  }
};

Custom Tool Registration

Register tools that your custom agent (or workflow agents) can call:

Tool Definition

{
  "name": "get_inventory",
  "description": "Fetch current inventory for a product SKU",
  "parameters": {
    "type": "object",
    "properties": {
      "sku": { "type": "string", "description": "Product SKU" }
    },
    "required": ["sku"]
  },
  "endpoint": "https://internal-api.company.com/inventory"
}

Register via API

curl -X POST "https://api.yourdomain.com/v1/tools" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "get_inventory",
    "description": "Fetch current inventory for a product SKU",
    "parameters": {
      "type": "object",
      "properties": {
        "sku": { "type": "string", "description": "Product SKU" }
      },
      "required": ["sku"]
    },
    "handler": {
      "type": "http",
      "url": "https://internal-api.company.com/inventory",
      "method": "GET"
    }
  }'

Tool Handler Types

TypeDescription
httpCall external HTTP endpoint
functionInvoke serverless function (e.g., AWS Lambda)
inlineExecute inline script (sandboxed)

Integration with External APIs

Custom agents can call any HTTP API. Use environment variables for secrets:

async execute(input: Record<string, unknown>) {
  const apiKey = process.env.EXTERNAL_API_KEY;
  const response = await fetch("https://api.external.com/v1/process", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${apiKey}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify(input)
  });
  return response.json();
}

Best Practices

  • Secrets — Store API keys in NFYio secrets manager or environment variables, never in code
  • Timeouts — Set reasonable timeouts for external calls (e.g., 30s)
  • Retries — Implement exponential backoff for transient failures
  • Validation — Validate API responses before returning to the workflow

Deployment in VPC Private Subnets

For internal APIs that are not exposed to the internet, deploy custom agents in VPC private subnets:

┌─────────────────────────────────────────────────────────────────┐
│                     NFYio VPC                                    │
│                                                                  │
│  ┌─────────────────────┐     ┌─────────────────────────────────┐ │
│  │  Public Subnet      │     │  Private Subnet                 │ │
│  │  • Load Balancer    │     │  • Custom Agent Pods             │ │
│  │  • API Gateway      │────►│  • Internal API Access           │ │
│  └─────────────────────┘     │  • No Internet Egress            │ │
│                              └─────────────────────────────────┘ │
│                                          │                        │
│                                          ▼                        │
│                              ┌─────────────────────────────────┐ │
│                              │  Internal Services              │ │
│                              │  • ERP, CRM, Inventory APIs     │ │
│                              └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

Configuration

# deployment.yaml
agent:
  name: internal-router
  type: custom
  vpc:
    subnetIds:
      - subnet-0abc123  # Private subnet
    securityGroupIds:
      - sg-0def456
  env:
    - name: INTERNAL_API_URL
      value: "http://internal-api.internal:8080"

Benefits

  • No public exposure — Internal APIs stay behind the VPC
  • Low latency — Same network as your internal services
  • Compliance — Data never leaves your network

Custom Agent SDK

Use the NFYio Agent SDK to build and test custom agents locally:

npm install @nfyio/agent-sdk
import { createCustomAgent, registerTool } from "@nfyio/agent-sdk";

const agent = createCustomAgent({
  name: "my-agent",
  execute: async (input) => {
    const result = await myLogic(input);
    return result;
  }
});

// Register and deploy
await agent.deploy({ workspaceId: "ws_123" });

Policy Gateway for Custom Tools

Custom tools are subject to the same policy gateway as built-in tools. Add rules for your custom tools:

{
  "policyGateway": {
    "rules": [
      {
        "tool": "get_inventory",
        "action": "allow",
        "scope": ["workspace:ws_123"]
      }
    ]
  }
}

Example: Full Custom Agent

{
  "name": "order-status-agent",
  "type": "custom",
  "image": "registry.yourdomain.com/nfyio/order-agent:1.0",
  "tools": ["get_inventory", "get_order_status", "notify_customer"],
  "vpc": {
    "subnetIds": ["subnet-private-1"],
    "securityGroupIds": ["sg-agent"]
  },
  "env": {
    "ORDER_API_URL": "https://orders.internal",
    "NOTIFY_API_URL": "https://notify.internal"
  }
}

Next Steps