Skip to content

Adapters

Framework adapters for integrating the agent server.

Express Adapter

createExpressMiddleware

Creates Express middleware from an agent server.

typescript
import { createExpressMiddleware } from '@cognipeer/agent-server';

const middleware = createExpressMiddleware(agentServer);
app.use(middleware);

Parameters

ParameterTypeDescription
agentServerAgentServerThe agent server instance

Returns

RequestHandler - Express middleware function.

Example

typescript
import express from 'express';
import { createAgentServer, createExpressMiddleware } from '@cognipeer/agent-server';

const agentServer = createAgentServer({
  basePath: '/api/agents',
  storage,
});

const app = express();
app.use(express.json());
app.use(createExpressMiddleware(agentServer));

app.listen(3000);

How It Works

The Express adapter:

  1. Extracts path, method, query, body from Express request
  2. Extracts auth token from headers
  3. Validates token with auth provider
  4. Calls agentServer.handleRequest()
  5. Translates RouteResult to Express response
  6. Handles SSE streaming for stream responses

Streaming Support

For streaming responses, the adapter sets up SSE:

typescript
// The adapter handles this automatically
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');

for await (const chunk of result.stream) {
  res.write(chunk);
}
res.end();

Next.js Adapter

createNextRouteHandlers

Creates Next.js App Router handlers.

typescript
import { createNextRouteHandlers } from '@cognipeer/agent-server';

export const { GET, POST, PATCH, DELETE, OPTIONS } = createNextRouteHandlers(agentServer);

Parameters

ParameterTypeDescription
agentServerAgentServerThe agent server instance

Returns

typescript
interface NextRouteHandlers {
  GET: (request: Request, context: { params: any }) => Promise<Response>;
  POST: (request: Request, context: { params: any }) => Promise<Response>;
  PATCH: (request: Request, context: { params: any }) => Promise<Response>;
  DELETE: (request: Request, context: { params: any }) => Promise<Response>;
  OPTIONS: (request: Request, context: { params: any }) => Promise<Response>;
}

Example

typescript
// app/api/agents/[...path]/route.ts
import { createAgentServer, createNextRouteHandlers } from '@cognipeer/agent-server';

const agentServer = createAgentServer({
  basePath: '/api/agents',
  storage,
});

await storage.connect();

export const { GET, POST, PATCH, DELETE, OPTIONS } = createNextRouteHandlers(agentServer);

Route Pattern

Use a catch-all route pattern:

app/api/agents/[...path]/route.ts

This catches all routes under /api/agents/*.

Streaming Support

The Next.js adapter uses ReadableStream for SSE:

typescript
return new Response(
  new ReadableStream({
    async start(controller) {
      for await (const chunk of result.stream) {
        controller.enqueue(new TextEncoder().encode(chunk));
      }
      controller.close();
    },
  }),
  {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
    },
  }
);

Custom Adapter

Create your own adapter for other frameworks:

typescript
import { AgentServer, RouteContext, RouteResult } from '@cognipeer/agent-server';

function createCustomAdapter(agentServer: AgentServer) {
  return async function handleRequest(req: CustomRequest, res: CustomResponse) {
    // 1. Extract request info
    const method = req.method;
    const path = req.path.replace(agentServer.config.basePath, '');
    
    // 2. Build route context
    const context: RouteContext = {
      params: {},
      query: req.query,
      body: req.body,
    };
    
    // 3. Handle authentication
    if (agentServer.config.auth?.enabled) {
      const token = extractToken(req.headers);
      if (token) {
        const result = await agentServer.config.auth.provider.validate(token);
        if (result.valid) {
          context.user = { id: result.userId! };
        } else {
          return res.status(401).json({ error: 'Unauthorized' });
        }
      }
    }
    
    // 4. Handle request
    const result = await agentServer.handleRequest(method, path, context);
    
    // 5. Send response
    if (result.stream) {
      // Handle streaming
      res.setHeader('Content-Type', 'text/event-stream');
      for await (const chunk of result.stream) {
        res.write(chunk);
      }
      res.end();
    } else if (result.raw) {
      // Handle binary response
      res.setHeader('Content-Type', result.headers?.['Content-Type'] || 'application/octet-stream');
      res.send(result.raw);
    } else {
      // Handle JSON response
      res.status(result.status).json(result.body);
    }
  };
}

function extractToken(headers: Record<string, string>): string | undefined {
  const auth = headers.authorization || headers.Authorization;
  if (auth?.startsWith('Bearer ')) {
    return auth.slice(7);
  }
  return undefined;
}

Fastify Example

typescript
import Fastify from 'fastify';
import { createAgentServer } from '@cognipeer/agent-server';

const fastify = Fastify();
const agentServer = createAgentServer({ basePath: '/api', storage });

// Custom Fastify handler
fastify.all('/api/*', async (request, reply) => {
  const path = request.url.replace('/api', '');
  
  const context = {
    params: {},
    query: request.query as Record<string, string>,
    body: request.body,
  };
  
  const result = await agentServer.handleRequest(
    request.method,
    path,
    context
  );
  
  if (result.stream) {
    reply.header('Content-Type', 'text/event-stream');
    for await (const chunk of result.stream) {
      reply.raw.write(chunk);
    }
    reply.raw.end();
  } else {
    reply.status(result.status).send(result.body);
  }
});

await storage.connect();
await fastify.listen({ port: 3000 });

Hono Example

typescript
import { Hono } from 'hono';
import { createAgentServer } from '@cognipeer/agent-server';

const app = new Hono();
const agentServer = createAgentServer({ basePath: '/api', storage });

app.all('/api/*', async (c) => {
  const path = c.req.path.replace('/api', '');
  
  const context = {
    params: {},
    query: Object.fromEntries(new URL(c.req.url).searchParams),
    body: await c.req.json().catch(() => undefined),
  };
  
  const result = await agentServer.handleRequest(
    c.req.method,
    path,
    context
  );
  
  if (result.stream) {
    return new Response(
      new ReadableStream({
        async start(controller) {
          for await (const chunk of result.stream) {
            controller.enqueue(new TextEncoder().encode(chunk));
          }
          controller.close();
        },
      }),
      { headers: { 'Content-Type': 'text/event-stream' } }
    );
  }
  
  return c.json(result.body, result.status);
});

export default app;

Studio · Pulse · Console · Agent SDK and more — the Cognipeer documentation hub