Skip to main content

Constructor

const agent = new ExuluAgent(options: ExuluAgentParams);
Creates a new ExuluAgent instance. See the configuration guide for all available options.

Methods

generateSync()

Generates a synchronous (non-streaming) response from the agent.
async generateSync({
  prompt,
  user,
  session,
  inputMessages,
  currentTools,
  allExuluTools,
  statistics,
  toolConfigs,
  providerapikey,
  contexts,
  rerankers,
  exuluConfig,
  outputSchema,
  agentInstance,
  instructions,
  req
}: GenerateSyncOptions): Promise<string | object>
prompt
string
The user’s prompt or question (mutually exclusive with inputMessages)
inputMessages
UIMessage[]
Array of conversation messages (mutually exclusive with prompt)
user
User
User object for access control and personalization
session
string
Session ID to load previous conversation history
currentTools
ExuluTool[]
Tools available to the agent during this execution
allExuluTools
ExuluTool[]
Complete list of all available tools (for nested tool calling)
statistics
ExuluStatisticParams
Statistics tracking configuration with label and trigger
toolConfigs
ExuluAgentToolConfig[]
Tool-specific configuration overrides
providerapikey
string
API key for the LLM provider (overrides default)
contexts
ExuluContext[]
Available contexts for semantic search
rerankers
ExuluReranker[]
Available rerankers for search optimization
exuluConfig
ExuluConfig
ExuluApp configuration object
outputSchema
z.ZodType
Zod schema for structured output generation
agentInstance
Agent
Agent database record with configuration
instructions
string
Override default instructions for this execution
req
Request
Express request object for context
return
Promise<string | object>
Generated text response, or structured object if outputSchema is provided
// Simple text generation
const response = await agent.generateSync({
  prompt: "What is the capital of France?",
  agentInstance: agentData,
  currentTools: [],
  statistics: {
    label: "assistant",
    trigger: "api"
  }
});

console.log(response); // "The capital of France is Paris."

// With tools
const response = await agent.generateSync({
  prompt: "Search our docs for authentication information",
  agentInstance: agentData,
  currentTools: [documentSearchTool, databaseTool],
  contexts: [docsContext],
  statistics: {
    label: "assistant",
    trigger: "api"
  }
});

// Structured output
const data = await agent.generateSync({
  prompt: "Extract contact information from this email",
  outputSchema: z.object({
    name: z.string(),
    email: z.string().email(),
    phone: z.string().optional()
  }),
  agentInstance: agentData,
  statistics: {
    label: "extractor",
    trigger: "api"
  }
});

console.log(data.name);  // Type-safe access
console.log(data.email);
Use generateSync() for API endpoints, background jobs, or when you need the complete response before proceeding.

generateStream()

Generates a streaming response from the agent for real-time output.
async generateStream({
  user,
  session,
  agentInstance,
  message,
  previousMessages,
  currentTools,
  approvedTools,
  allExuluTools,
  toolConfigs,
  providerapikey,
  contexts,
  rerankers,
  exuluConfig,
  instructions,
  req
}: GenerateStreamOptions): Promise<{
  stream: ReturnType<typeof streamText>;
  originalMessages: UIMessage[];
  previousMessages: UIMessage[];
}>
message
UIMessage
required
The new user message to process
session
string
Session ID to load and continue conversation history
user
User
User object for access control
agentInstance
Agent
Agent database record with configuration
previousMessages
UIMessage[]
Previous messages to include in context
currentTools
ExuluTool[]
Tools available to the agent
approvedTools
string[]
Tool IDs that have been pre-approved for execution
allExuluTools
ExuluTool[]
Complete list of all tools
toolConfigs
ExuluAgentToolConfig[]
Tool configuration overrides
providerapikey
string
API key override
contexts
ExuluContext[]
Available contexts
rerankers
ExuluReranker[]
Available rerankers
exuluConfig
ExuluConfig
App configuration
instructions
string
Override instructions
req
Request
Express request object
stream
StreamTextResult
AI SDK stream object with text chunks and tool calls
originalMessages
UIMessage[]
All messages including the new one
previousMessages
UIMessage[]
Messages from before this request
// Stream a response
const { stream, originalMessages } = await agent.generateStream({
  message: {
    id: "msg-123",
    role: "user",
    parts: [{ type: "text", text: "Tell me about your services" }]
  },
  session: sessionId,
  user: currentUser,
  agentInstance: agentData,
  currentTools: tools,
  contexts: contexts,
  exuluConfig: config
});

// Consume the stream
for await (const chunk of stream.textStream) {
  process.stdout.write(chunk);
}

// Or use with Express
app.post("/chat", async (req, res) => {
  const { stream } = await agent.generateStream({
    message: req.body.message,
    session: req.body.session,
    user: req.user,
    agentInstance: agentData,
    currentTools: tools
  });

  return stream.toDataStreamResponse();
});
Use generateStream() for interactive chat applications where you want to display responses progressively.

tool()

Exports the agent as a tool that other agents can call.
async tool(
  instance: string,
  agents: ExuluAgent[],
  contexts: ExuluContext[],
  rerankers: ExuluReranker[]
): Promise<ExuluTool | null>
instance
string
required
Agent ID to load from the database
agents
ExuluAgent[]
required
Array of all available agents
contexts
ExuluContext[]
required
Array of all available contexts
rerankers
ExuluReranker[]
required
Array of all available rerankers
return
Promise<ExuluTool | null>
Tool instance that wraps the agent, or null if agent not found
// Create specialist agent
const sqlAgent = new ExuluAgent({
  id: "sql_specialist",
  name: "SQL Specialist",
  type: "agent",
  description: "Expert at writing SQL queries",
  provider: "openai",
  config: {
    name: "gpt-4o",
    model: { /* ... */ },
    instructions: "You are an expert SQL developer."
  },
  capabilities: { text: true, images: [], files: [], audio: [], video: [] }
});

// Export as tool
const sqlTool = await sqlAgent.tool(
  "sql_specialist",
  [sqlAgent],
  contexts,
  rerankers
);

// Main agent can use it
const mainAgent = new ExuluAgent({
  id: "assistant",
  name: "Assistant",
  // ... config
});

const response = await mainAgent.generateSync({
  prompt: "Write a query to find top customers",
  currentTools: [sqlTool], // Delegates to SQL specialist
  // ... other params
});
Use agent-as-tool for multi-agent workflows where specialized agents handle specific tasks.

Properties

id

id
string
Unique agent identifier
console.log(agent.id); // "customer_support_agent"

name

name
string
Human-readable agent name
console.log(agent.name); // "Customer Support Agent"

provider

provider
string
LLM provider name
console.log(agent.provider); // "openai"

providerName

providerName
string
Computed provider name (empty string if no model configured)
console.log(agent.providerName); // "openai"

modelName

modelName
string
Computed model name from config
console.log(agent.modelName); // "gpt-4o"

description

description
string
Agent description
console.log(agent.description); // "Handles customer support inquiries"

type

type
'agent'
Always "agent"
console.log(agent.type); // "agent"

slug

slug
string
URL-friendly slug for the agent
console.log(agent.slug); // "/agents/customer-support-agent/run"

capabilities

capabilities
Capabilities
Supported input types
console.log(agent.capabilities);
// {
//   text: true,
//   images: [".png", ".jpg"],
//   files: [".pdf", ".txt"],
//   audio: [],
//   video: []
// }

config

config
ExuluAgentConfig | undefined
Agent configuration including model and instructions
console.log(agent.config?.name); // "gpt-4o"
console.log(agent.config?.instructions); // "You are a helpful assistant..."

model

model
ModelFactory | undefined
Model factory function
const languageModel = agent.model?.create({ apiKey: "..." });

maxContextLength

maxContextLength
number | undefined
Maximum context window size in tokens
console.log(agent.maxContextLength); // 128000

workflows

workflows
WorkflowConfig | undefined
Workflow configuration
console.log(agent.workflows?.enabled); // true

queue

queue
ExuluQueueConfig | undefined
Queue configuration
console.log(agent.queue?.name); // "agent_tasks"

rateLimit

rateLimit
RateLimiterRule | undefined
Rate limiting configuration
console.log(agent.rateLimit?.points); // 100

Usage examples

Basic text generation

import { ExuluAgent } from "@exulu/backend";
import { createOpenAI } from "@ai-sdk/openai";

const agent = new ExuluAgent({
  id: "assistant",
  name: "Assistant",
  type: "agent",
  description: "General AI assistant",
  provider: "openai",
  config: {
    name: "gpt-4o",
    model: {
      create: ({ apiKey }) => createOpenAI({ apiKey })("gpt-4o")
    },
    instructions: "You are a helpful assistant."
  },
  capabilities: {
    text: true,
    images: [],
    files: [],
    audio: [],
    video: []
  }
});

const response = await agent.generateSync({
  prompt: "Explain quantum computing in simple terms",
  agentInstance: await loadAgent("assistant"),
  statistics: { label: "assistant", trigger: "api" }
});

console.log(response);

Streaming chat

const { stream } = await agent.generateStream({
  message: {
    id: "msg-123",
    role: "user",
    parts: [{ type: "text", text: "Write a poem about AI" }]
  },
  session: "session-abc",
  user: currentUser,
  agentInstance: agentData,
  currentTools: []
});

// Stream to console
for await (const chunk of stream.textStream) {
  process.stdout.write(chunk);
}

With tools

import { ExuluTool } from "@exulu/backend";
import { z } from "zod";

// Define a tool
const weatherTool = new ExuluTool({
  id: "weather",
  name: "get_weather",
  description: "Gets weather for a location",
  type: "function",
  inputSchema: z.object({
    location: z.string()
  }),
  config: [],
  execute: async ({ location }) => {
    const weather = await fetchWeather(location);
    return { result: JSON.stringify(weather) };
  }
});

// Use with agent
const response = await agent.generateSync({
  prompt: "What's the weather in Paris?",
  agentInstance: agentData,
  currentTools: [weatherTool],
  statistics: { label: "assistant", trigger: "api" }
});

Structured output

import { z } from "zod";

const ContactSchema = z.object({
  name: z.string(),
  email: z.string().email(),
  phone: z.string().optional(),
  company: z.string().optional(),
  role: z.string().optional()
});

const contacts = await agent.generateSync({
  prompt: `Extract all contact information from this email:

  Hi, I'm John Smith from Acme Corp. You can reach me at
  john@acme.com or call me at 555-1234. I'm the CTO.`,
  outputSchema: ContactSchema,
  agentInstance: agentData,
  statistics: { label: "extractor", trigger: "api" }
});

console.log(contacts.name);    // "John Smith"
console.log(contacts.email);   // "john@acme.com"
console.log(contacts.company); // "Acme Corp"
console.log(contacts.role);    // "CTO"

With conversation history

// First message
const { stream: stream1 } = await agent.generateStream({
  message: {
    id: "msg-1",
    role: "user",
    parts: [{ type: "text", text: "My name is Alice" }]
  },
  session: "session-123",
  user: currentUser,
  agentInstance: agentData,
  currentTools: []
});

await stream1.toTextStreamResponse(); // Wait for completion

// Second message - agent remembers context
const { stream: stream2 } = await agent.generateStream({
  message: {
    id: "msg-2",
    role: "user",
    parts: [{ type: "text", text: "What's my name?" }]
  },
  session: "session-123", // Same session
  user: currentUser,
  agentInstance: agentData,
  currentTools: []
});

// Agent responds: "Your name is Alice."

With memory

// Configure agent with memory
const agent = new ExuluAgent({
  id: "memory_agent",
  name: "Agent with Memory",
  type: "agent",
  description: "Agent that remembers past interactions",
  provider: "openai",
  config: {
    name: "gpt-4o",
    model: { /* ... */ },
    instructions: "You are an assistant with memory.",
    memory: "agent_memory_context" // Context ID
  },
  capabilities: { text: true, images: [], files: [], audio: [], video: [] }
});

// Agent automatically searches memory before responding
const response = await agent.generateSync({
  prompt: "What did we discuss about the project last week?",
  agentInstance: agentData,
  contexts: [memoryContext], // Include memory context
  statistics: { label: "memory_agent", trigger: "api" }
});

// Agent can also create new memories via the auto-generated tool

Multi-agent workflow

// Create specialist agents
const researchAgent = new ExuluAgent({
  id: "researcher",
  name: "Research Specialist",
  type: "agent",
  description: "Conducts research and gathers information",
  provider: "openai",
  config: {
    name: "gpt-4o",
    model: { /* ... */ },
    instructions: "You are a research specialist. Gather comprehensive information."
  },
  capabilities: { text: true, images: [], files: [], audio: [], video: [] }
});

const writerAgent = new ExuluAgent({
  id: "writer",
  name: "Content Writer",
  type: "agent",
  description: "Writes content based on research",
  provider: "anthropic",
  config: {
    name: "claude-opus-4",
    model: { /* ... */ },
    instructions: "You are a skilled writer. Create engaging, well-structured content."
  },
  capabilities: { text: true, images: [], files: [], audio: [], video: [] }
});

// Coordinator agent that delegates
const coordinatorAgent = new ExuluAgent({
  id: "coordinator",
  name: "Coordinator",
  type: "agent",
  description: "Coordinates workflow between specialists",
  provider: "openai",
  config: {
    name: "gpt-4o",
    model: { /* ... */ },
    instructions: "You coordinate work between specialists."
  },
  capabilities: { text: true, images: [], files: [], audio: [], video: [] }
});

// Export specialists as tools
const researchTool = await researchAgent.tool("researcher", [researchAgent], [], []);
const writerTool = await writerAgent.tool("writer", [writerAgent], [], []);

// Coordinator uses them
const article = await coordinatorAgent.generateSync({
  prompt: "Create an article about quantum computing",
  currentTools: [researchTool, writerTool],
  agentInstance: await loadAgent("coordinator"),
  statistics: { label: "coordinator", trigger: "api" }
});

Processing files

const documentAgent = new ExuluAgent({
  id: "doc_processor",
  name: "Document Processor",
  type: "agent",
  description: "Processes and analyzes documents",
  provider: "openai",
  config: {
    name: "gpt-4o",
    model: { /* ... */ },
    instructions: "Analyze documents and extract key information."
  },
  capabilities: {
    text: true,
    images: [],
    files: [".pdf", ".docx", ".txt"],
    audio: [],
    video: []
  }
});

// Files are automatically converted to text
const { stream } = await documentAgent.generateStream({
  message: {
    id: "msg-1",
    role: "user",
    parts: [
      { type: "text", text: "Summarize this document" },
      {
        type: "file",
        mediaType: "application/pdf",
        url: "https://example.com/document.pdf",
        filename: "document.pdf"
      }
    ]
  },
  session: sessionId,
  user: currentUser,
  agentInstance: agentData,
  currentTools: []
});

Type definitions

// Agent constructor parameters
interface ExuluAgentParams {
  id: string;
  name: string;
  type: "agent";
  description: string;
  config?: ExuluAgentConfig;
  queue?: ExuluQueueConfig;
  maxContextLength?: number;
  authenticationInformation?: string;
  provider: string;
  workflows?: {
    enabled: boolean;
    queue?: Promise<ExuluQueueConfig>;
  };
  capabilities?: {
    text: boolean;
    images: imageTypes[];
    files: fileTypes[];
    audio: audioTypes[];
    video: videoTypes[];
  };
  rateLimit?: RateLimiterRule;
}

// Agent configuration
interface ExuluAgentConfig {
  name: string;
  model?: {
    create: ({ apiKey }: { apiKey?: string }) => LanguageModel;
  };
  instructions?: string;
  memory?: string;
}

// Capabilities types
type imageTypes = '.png' | '.jpg' | '.jpeg' | '.gif' | '.webp';
type fileTypes = '.pdf' | '.docx' | '.xlsx' | '.xls' | '.csv' |
                 '.pptx' | '.ppt' | '.txt' | '.md' | '.json';
type audioTypes = '.mp3' | '.wav' | '.m4a' | '.mp4' | '.mpeg';
type videoTypes = '.mp4' | '.m4a' | '.mp3' | '.mpeg' | '.wav';

Best practices

Test with different prompts: Agent behavior can vary significantly with different phrasings. Test edge cases and refine instructions.
Monitor token usage: Track input/output tokens to optimize costs and prevent context window overflow.
Validate structured outputs: Even with schemas, validate critical data before using it in production systems.
Tool selection: Provide only necessary tools. Too many tools can confuse the agent and increase latency.

Next steps