GameCraftGameCraft

AI Agent Providers

Polymorphic agent provider system for flexible AI integrations

AI Agent Providers

ProductReady supports a polymorphic architecture for multiple AI Agent providers, allowing flexible use of different AI frameworks within the same application.

Overview

The Agent Provider system uses manual instantiation design, supporting multiple different providers simultaneously in a single application. No environment variable configuration required - all providers are created directly with the new keyword.

Supported Providers

ProviderComplexityUse CaseStatus
AI SDKSimpleDirect LLM calls✅ Ready
Gaia AgentMediumAdvanced agent features✅ Ready
LangChainComplexAdvanced workflows⚠️ Stub

Quick Start

1. Manual Instantiation

The most direct approach - create providers with new:

import { GaiaAgentProvider } from "agentlib/providers";

// Create provider instance
const provider = new GaiaAgentProvider({
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
});

// Use provider
const result = await provider.stream(messages);

2. Multiple Providers

Use different providers simultaneously in the same application:

import { AiSdkProvider, GaiaAgentProvider } from "agentlib/providers";

// AI SDK for simple queries
const simpleProvider = new AiSdkProvider({
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
});

// Gaia Agent for complex tasks
const complexProvider = new GaiaAgentProvider({
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
  tools: customTools,
});

// Use as needed
const quickResult = await simpleProvider.stream(quickQuery);
const complexResult = await complexProvider.stream(complexQuery);

3. Factory Methods

Use factory methods to create providers (optional):

import { AgentProviderFactory } from "agentlib/providers";

const provider = AgentProviderFactory.createAiSdkProvider(config);
const provider2 = AgentProviderFactory.createGaiaAgentProvider(config);

Provider Details

AI SDK Provider

Direct integration of Vercel AI SDK's streamText functionality.

Advantages:

  • Simplest implementation
  • Minimal dependencies
  • Direct LLM access
  • Built-in tool calling

Use Cases:

  • Simple LLM conversations
  • No special agent features needed
  • Minimal dependencies desired

Example:

import { AiSdkProvider } from "agentlib/providers";

const provider = new AiSdkProvider({
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
});

const messages = [
  { role: "user", content: "Hello!" }
];

const result = await provider.stream(messages);

Gaia Agent Provider

Advanced agent capabilities based on @gaia-agent/sdk.

Advantages:

  • Extended tool ecosystem
  • Browser automation support
  • Sandbox execution support
  • Production-ready

Use Cases:

  • Browser automation needed
  • Sandbox execution required
  • Complex agent tasks
  • Default recommendation

Example:

import { GaiaAgentProvider } from "agentlib/providers";

const provider = new GaiaAgentProvider({
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
  tools: {
    generate_article: {
      description: "Generate an article",
      inputSchema: z.object({ title: z.string() }),
      execute: async (input) => { /* ... */ },
    },
  },
});

LangChain Provider

LangChain framework integration (pending implementation).

Advantages:

  • Extensive ecosystem
  • Advanced agent patterns
  • Memory and chain support

Status: ⚠️ Requires dependencies

pnpm add langchain @langchain/openai @langchain/core

Real-World Scenarios

Scenario 1: Different Providers for Different Routes

// /api/chat/route.ts - AI SDK for simple conversations
import { AiSdkProvider } from "agentlib/providers";

export async function POST(req: Request) {
  const provider = new AiSdkProvider({
    model: "gpt-4",
    apiKey: process.env.OPENAI_API_KEY,
  });
  
  const result = await provider.stream(messages);
  return result.toUIMessageStreamResponse({});
}
// /api/agent/task/route.ts - Gaia Agent for complex tasks
import { GaiaAgentProvider } from "agentlib/providers";

export async function POST(req: Request) {
  const provider = new GaiaAgentProvider({
    model: "gpt-4",
    apiKey: process.env.OPENAI_API_KEY,
    tools: getCustomTools(),
  });
  
  const result = await provider.stream(messages);
  return result.toUIMessageStreamResponse({});
}

Scenario 2: Provider Fallback

import { GaiaAgentProvider, AiSdkProvider } from "agentlib/providers";

const config = {
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
};

try {
  // Try primary provider
  const primary = new GaiaAgentProvider(config);
  return await primary.stream(messages);
} catch (error) {
  console.error("Primary failed, using fallback:", error);
  
  // Fallback to simpler provider
  const fallback = new AiSdkProvider(config);
  return await fallback.stream(messages);
}

Scenario 3: Task Type Routing

import { AiSdkProvider, GaiaAgentProvider } from "agentlib/providers";

function getProviderForTask(taskType: string) {
  const config = {
    model: "gpt-4",
    apiKey: process.env.OPENAI_API_KEY,
  };

  switch (taskType) {
    case "simple_chat":
      return new AiSdkProvider(config);
      
    case "article_generation":
      return new GaiaAgentProvider({
        ...config,
        tools: getArticleTools(),
      });
      
    case "research":
      return new GaiaAgentProvider({
        ...config,
        tools: getResearchTools(),
      });
      
    default:
      return new AiSdkProvider(config);
  }
}

Custom Tools

All providers support the AI SDK Tool interface:

import { tool } from "ai";
import { z } from "zod";

const customTools = {
  get_weather: tool({
    description: "Get weather for a location",
    inputSchema: z.object({
      location: z.string(),
    }),
    execute: async ({ location }) => {
      // Implement weather query
      return { temperature: 72, condition: "sunny" };
    },
  }),
};

const provider = new GaiaAgentProvider({
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
  tools: customTools,
});

Streaming Responses

All providers return AI SDK-compatible streaming responses:

const provider = new GaiaAgentProvider(config);
const result = await provider.stream(messages);

const response = result.toUIMessageStreamResponse({
  onFinish: async ({ messages }) => {
    console.log("Stream completed:", messages);
    // Save messages to database
    await saveMessages(messages);
  },
});

return response; // Return to client

Configuration Options

AgentProviderConfig

interface AgentProviderConfig {
  // Model identifier
  model: string;
  
  // API key (optional, defaults to environment variable)
  apiKey?: string;
  
  // Custom API endpoint (optional)
  baseURL?: string;
  
  // Custom tools
  tools?: Record<string, Tool>;
  
  // Provider-specific options
  options?: Record<string, unknown>;
}

Complete Example

const config: AgentProviderConfig = {
  model: "gpt-4",
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: process.env.OPENAI_BASE_URL,
  tools: {
    custom_tool: tool({
      description: "My custom tool",
      inputSchema: z.object({ input: z.string() }),
      execute: async (input) => ({ result: "done" }),
    }),
  },
  options: {
    // Provider-specific configuration
    maxRetries: 3,
    timeout: 30000,
  },
};

const provider = new GaiaAgentProvider(config);

Best Practices

1. Choose Provider by Task

// ✅ Good: Choose based on task complexity
const simpleProvider = new AiSdkProvider(config);      // Simple chat
const complexProvider = new GaiaAgentProvider(config);  // Complex tasks

2. Reuse Provider Instances

// ✅ Good: Reuse across requests (if possible)
class AgentService {
  private provider: AgentProvider;
  
  constructor() {
    this.provider = new GaiaAgentProvider(config);
  }
  
  async chat(messages: CoreMessage[]) {
    return this.provider.stream(messages);
  }
}

3. Handle Errors Properly

// ✅ Good: Gracefully handle provider errors
try {
  const result = await provider.stream(messages);
  return result.toUIMessageStreamResponse({});
} catch (error) {
  if (error instanceof Error) {
    console.error("Provider error:", error.message);
    // Log error or fallback to alternative provider
  }
  throw error;
}

4. Clean Up Resources

// ✅ Good: Clean up provider after use
const provider = new GaiaAgentProvider(config);
try {
  const result = await provider.stream(messages);
  return result.toUIMessageStreamResponse({});
} finally {
  if (provider.dispose) {
    await provider.dispose();
  }
}

Performance Optimization

Provider Instance Reuse

// Create singleton provider
let cachedProvider: AgentProvider | null = null;

function getProvider(): AgentProvider {
  if (!cachedProvider) {
    cachedProvider = new GaiaAgentProvider(config);
  }
  return cachedProvider;
}

On-Demand Creation

// Create different providers as needed
function createProviderForRoute(route: string): AgentProvider {
  const config = getConfigForRoute(route);
  
  if (route.startsWith("/api/simple")) {
    return new AiSdkProvider(config);
  }
  
  return new GaiaAgentProvider(config);
}

Troubleshooting

Provider Creation Failed

Issue:

Error: Provider initialization failed

Solution:

  • Check API key is correct
  • Verify model name is valid
  • Ensure network connection is working

Tool Execution Error

Issue:

Tool execution failed: ...

Solution:

  • Check tool's inputSchema is correct
  • Verify execute function implementation
  • Add error handling and logging

LangChain Provider Unavailable

Issue:

LangChain provider not yet implemented

Solution: Install required dependencies:

pnpm add langchain @langchain/openai @langchain/core

Next Steps

On this page