Lucid Agents
Packages

@lucid-agents/express

Express framework adapter for running agents.

The Express adapter creates an Express application from an agent runtime, exposing all entrypoints as HTTP routes.

Installation

bun add @lucid-agents/express express

For TypeScript:

bun add -D @types/express

For payments support:

bun add x402-express

Basic usage

import { createAgent } from '@lucid-agents/core';
import { http } from '@lucid-agents/http';
import { createAgentApp } from '@lucid-agents/express';
import { z } from 'zod';

const agent = await createAgent({
  name: 'my-agent',
  version: '1.0.0',
})
  .use(http())
  .build();

const { app, addEntrypoint } = await createAgentApp(agent);

addEntrypoint({
  key: 'greet',
  input: z.object({ name: z.string() }),
  async handler({ input }) {
    return { output: { message: `Hello, ${input.name}!` } };
  },
});

app.listen(3000, () => {
  console.log('Agent running at http://localhost:3000');
});

API reference

createAgentApp(agent, options?)

Creates an Express app from an agent runtime.

function createAgentApp(
  agent: AgentRuntime,
  options?: CreateAgentAppOptions
): Promise<{
  app: Express;
  addEntrypoint: (def: EntrypointDef) => void;
}>

Parameters:

ParameterTypeDescription
agentAgentRuntimeBuilt agent runtime
optionsCreateAgentAppOptionsOptional configuration

Returns:

PropertyTypeDescription
appExpressConfigured Express application
addEntrypointFunctionAdd entrypoints after app creation

CreateAgentAppOptions

type CreateAgentAppOptions = {
  beforeMount?: (app: Express) => void;
  afterMount?: (app: Express) => void;
};

Example with hooks

import cors from 'cors';
import helmet from 'helmet';

const { app, addEntrypoint } = await createAgentApp(agent, {
  beforeMount: (app) => {
    // Add security middleware
    app.use(helmet());
    app.use(cors());

    // Add authentication
    app.use('/entrypoints', (req, res, next) => {
      const token = req.headers.authorization;
      if (!token) {
        return res.status(401).json({ error: 'Unauthorized' });
      }
      next();
    });
  },
  afterMount: (app) => {
    // Add custom routes
    app.get('/custom', (req, res) => {
      res.json({ custom: true });
    });

    // Add error handler
    app.use((err, req, res, next) => {
      console.error(err);
      res.status(500).json({ error: 'Internal error' });
    });
  },
});

Routes

The adapter registers these routes:

RouteMethodDescription
/GETLanding page (if enabled)
/.well-known/agent.jsonGETAgent Card manifest
/healthGETHealth check endpoint
/entrypointsGETList available entrypoints
/entrypoints/:key/invokePOSTInvoke an entrypoint
/entrypoints/:key/streamPOSTStream from an entrypoint (SSE)
/tasksGETList tasks
/tasks/:idGETGet task by ID
/tasks/:id/cancelPOSTCancel a task
/tasks/:id/subscribeGETSubscribe to task updates (SSE)
/favicon.icoGETFavicon

Payment middleware

Add x402 payment middleware for paid entrypoints:

import { createAgentApp, withPayments } from '@lucid-agents/express';

const agent = await createAgent(meta)
  .use(http())
  .use(payments({ config: paymentsFromEnv() }))
  .build();

const { app, addEntrypoint } = await createAgentApp(agent);

// Add paid entrypoint
addEntrypoint({
  key: 'premium',
  price: { invoke: '$0.01' },
  async handler({ input }) {
    return { output: { result: 'premium content' } };
  },
});

// Wrap app with payment middleware
withPayments(app, agent);

app.listen(3000);

withPayments(app, agent)

Adds x402 payment verification middleware.

function withPayments(app: Express, agent: AgentRuntime): void

The middleware:

  1. Checks if the entrypoint has a price
  2. Validates the X-Payment header
  3. Returns 402 Payment Required if invalid/missing
  4. Allows the request through if payment is valid

Full example

import express from 'express';
import cors from 'cors';
import { z } from 'zod';
import { createAgent } from '@lucid-agents/core';
import { http } from '@lucid-agents/http';
import { payments, paymentsFromEnv } from '@lucid-agents/payments';
import { createAgentApp, withPayments } from '@lucid-agents/express';

const agent = await createAgent({
  name: 'my-agent',
  version: '1.0.0',
  description: 'An AI-powered assistant',
})
  .use(http())
  .use(payments({ config: paymentsFromEnv() }))
  .build();

const { app, addEntrypoint } = await createAgentApp(agent, {
  beforeMount: (app) => {
    app.use(cors());
    app.use(express.json());
  },
});

// Free entrypoint
addEntrypoint({
  key: 'echo',
  input: z.object({ text: z.string() }),
  async handler({ input }) {
    return { output: { echoed: input.text } };
  },
});

// Paid entrypoint
addEntrypoint({
  key: 'analyze',
  input: z.object({ text: z.string() }),
  price: { invoke: '$0.01' },
  async handler({ input }) {
    return { output: { analysis: 'AI analysis...' } };
  },
});

// Add payment middleware
withPayments(app, agent);

const PORT = process.env.PORT ?? 3000;
app.listen(PORT, () => {
  console.log(`Agent running at http://localhost:${PORT}`);
});

Exports

// Main API
export { createAgentApp, withPayments } from '@lucid-agents/express';

// Types
export type { CreateAgentAppOptions } from '@lucid-agents/express';

On this page