Skip to main content
Agents are the core building blocks of AgentLIB. This guide shows you how to create agents using both configuration objects and decorator-based classes.

Quick Start

The simplest way to create an agent is with createAgent():
import { createAgent } from '@agentlib/core'
import { openai } from '@agentlib/openai'

const agent = createAgent({
  name: 'assistant',
  systemPrompt: 'You are a helpful assistant.',
})
  .provider(openai({ 
    apiKey: process.env.OPENAI_API_KEY,
    model: 'gpt-4o'
  }))

const result = await agent.run('Hello!')
console.log(result.output)

Configuration-Based Agents

1

Define the Agent Configuration

Start by creating an agent with basic configuration:
import { createAgent } from '@agentlib/core'
import { openai } from '@agentlib/openai'
import { BufferMemory } from '@agentlib/memory'

const agent = createAgent({
  name: 'weather-assistant',
  systemPrompt: 'You are a weather assistant. Use tools when appropriate.',
  data: { userId: 'default', plan: 'free' },
  policy: {
    maxSteps: 10,
    tokenBudget: 10_000,
  },
})
The data field lets you pass typed application state that’s available throughout the agent’s lifecycle.
2

Add a Model Provider

Chain a model provider to enable LLM capabilities:
agent.provider(openai({
  apiKey: process.env.OPENAI_API_KEY,
  model: 'gpt-4o',
  baseURL: 'https://api.openai.com/v1'
}))
3

Add Memory (Optional)

Enable conversation history with a memory provider:
import { BufferMemory } from '@agentlib/memory'

agent.memory(new BufferMemory({ maxMessages: 20 }))
4

Add Tools (Optional)

Equip your agent with tools:
import { defineTool } from '@agentlib/core'

const weatherTool = defineTool({
  schema: {
    name: 'get_weather',
    description: 'Get the current weather for a location.',
    parameters: {
      type: 'object',
      properties: {
        location: { type: 'string', description: 'The city' },
      },
      required: ['location'],
    },
  },
  async execute({ location }) {
    // Call weather API
    return { location, temperature: 22, condition: 'sunny' }
  },
})

agent.tool(weatherTool)
5

Run the Agent

Execute the agent with input:
const result = await agent.run({
  input: 'What is the weather in Tokyo?',
  sessionId: 'user-123',
  data: { userId: 'user-123', plan: 'pro' },
})

console.log(result.output)
console.log('Token usage:', result.state.usage)
console.log('Steps taken:', result.state.steps.length)

Class-Based Agents with Decorators

For complex agents, use the decorator pattern:
import 'reflect-metadata'
import { createAgent, Agent, Tool, Arg } from '@agentlib/core'
import { openai } from '@agentlib/openai'

@Agent({
  name: 'smart-assistant',
  systemPrompt: 'You are a helpful assistant with specialized tools.'
})
class MyAgent {
  @Tool({
    name: 'weather',
    description: 'Get the weather in a city.'
  })
  async weather(
    @Arg({ name: 'city', description: 'The city' }) city: string
  ) {
    return { city, temperature: '25°C' }
  }

  @Tool({
    name: 'calculate',
    description: 'Perform a calculation.'
  })
  async calculate(
    @Arg({ name: 'expression', description: 'Math expression' }) expression: string
  ) {
    return { result: eval(expression) }
  }
}

const agent = createAgent(MyAgent)
  .provider(openai({ apiKey: process.env.OPENAI_API_KEY }))

await agent.run('What is the weather in Paris?')
The decorator pattern requires reflect-metadata and proper TypeScript configuration with experimentalDecorators and emitDecoratorMetadata enabled.

Typed Agent Data

Agents support typed application state that persists across runs:
interface AppData {
  userId: string
  plan: 'free' | 'pro'
  credits: number
}

const agent = createAgent<AppData>({
  name: 'app-agent',
  data: { userId: 'default', plan: 'free', credits: 100 },
})
  .provider(model)
  .use({
    name: 'credit-guard',
    scope: 'run:before',
    async run(mCtx, next) {
      if (mCtx.ctx.data.credits <= 0) {
        throw new Error('Insufficient credits')
      }
      mCtx.ctx.data.credits -= 1
      await next()
    },
  })

const result = await agent.run({
  input: 'Hello',
  data: { userId: 'user-456', plan: 'pro', credits: 50 },
})

Agent Policies

Control agent behavior with policies:
const agent = createAgent({ name: 'agent' })
  .provider(model)
  .policy({
    maxSteps: 15,           // Maximum reasoning steps
    tokenBudget: 50_000,    // Maximum total tokens
    timeout: 30_000,        // Timeout in milliseconds
    allowedTools: ['search', 'calculator'], // Restrict tool access
    maxParallelTools: 3,    // Max concurrent tool calls
  })

Complete Example

Here’s a full example combining all features:
import 'dotenv/config'
import { createAgent, defineTool } from '@agentlib/core'
import { openai } from '@agentlib/openai'
import { BufferMemory } from '@agentlib/memory'
import { createLogger } from '@agentlib/logger'

interface AppData {
  userId: string
  plan: 'free' | 'pro'
}

const getWeatherTool = defineTool({
  schema: {
    name: 'get_weather',
    description: 'Get the current weather for a location.',
    parameters: {
      type: 'object',
      properties: {
        location: { type: 'string', description: 'The city' },
      },
      required: ['location'],
    },
  },
  async execute({ location }) {
    return { location, temperature: 22, condition: 'sunny' }
  },
})

const agent = createAgent<AppData>({
  name: 'assistant',
  systemPrompt: 'You are a helpful assistant.',
  data: { userId: 'default', plan: 'free' },
  policy: {
    maxSteps: 10,
    tokenBudget: 10_000,
  },
})
  .provider(openai({ 
    apiKey: process.env.OPENAI_API_KEY,
    model: 'gpt-4o'
  }))
  .memory(new BufferMemory({ maxMessages: 20 }))
  .tool(getWeatherTool)
  .use(createLogger({ level: 'debug' }))
  .use({
    name: 'plan-guard',
    scope: 'run:before',
    async run(mCtx, next) {
      if (mCtx.ctx.data.plan === 'free' && mCtx.ctx.input.length > 500) {
        throw new Error('Input too long for free plan')
      }
      await next()
    },
  })

agent.on('run:start', ({ input }) => {
  console.log(`[run:start] input="${input}"`)
})

agent.on('tool:after', ({ tool, result }) => {
  console.log(`[tool:after] ${tool} →`, result)
})

const result = await agent.run({
  input: 'What is the weather in Buenos Aires and Tokyo?',
  data: { userId: 'user-123', plan: 'pro' },
})

console.log('\nFinal response:')
console.log(result.output)
console.log('\nToken usage:', result.state.usage)
console.log('Steps taken:', result.state.steps.length)

Next Steps

Build docs developers (and LLMs) love