Integration Patterns

Patterns for integrating generated agents with other systems.

Generated agents can be integrated into various environments beyond the default CLI. This reference covers common integration patterns.

Interface Types

Agent Workshop supports multiple interface types:

InterfaceStatusDescription
CLIFull SupportInteractive command-line interface
WebScaffoldingWeb-based chat interface
APIScaffoldingREST API endpoint
DiscordScaffoldingDiscord bot
SlackScaffoldingSlack bot

Scaffolding interfaces provide a starting structure but require additional configuration and deployment setup.

Programmatic Usage

Import and use the agent directly in your code:

1import { MyAgent } from './src/agent';
2
3// Create agent instance
4const agent = new MyAgent({
5  apiKey: process.env.ANTHROPIC_API_KEY,
6  model: 'claude-sonnet-4-5-20250929'
7});
8
9// Send a query
10const response = await agent.query('Analyze the codebase structure');
11
12// Handle streaming response
13for await (const chunk of agent.stream('Explain this file')) {
14  process.stdout.write(chunk);
15}

Express API Integration

Wrap your agent in an Express API:

src/api.ts
1import express from 'express';
2import { MyAgent } from './agent';
3
4const app = express();
5app.use(express.json());
6
7const agent = new MyAgent({
8  apiKey: process.env.ANTHROPIC_API_KEY
9});
10
11app.post('/api/chat', async (req, res) => {
12  const { message, sessionId } = req.body;
13
14  try {
15    const response = await agent.query(message, { sessionId });
16    res.json({ response });
17  } catch (error) {
18    res.status(500).json({ error: error.message });
19  }
20});
21
22app.post('/api/chat/stream', async (req, res) => {
23  const { message, sessionId } = req.body;
24
25  res.setHeader('Content-Type', 'text/event-stream');
26  res.setHeader('Cache-Control', 'no-cache');
27  res.setHeader('Connection', 'keep-alive');
28
29  for await (const chunk of agent.stream(message, { sessionId })) {
30    res.write(`data: ${JSON.stringify({ chunk })}\n\n`);
31  }
32
33  res.write('data: [DONE]\n\n');
34  res.end();
35});
36
37app.listen(3000);

Discord Bot Integration

Create a Discord bot with your agent:

src/discord-bot.ts
1import { Client, GatewayIntentBits } from 'discord.js';
2import { MyAgent } from './agent';
3
4const client = new Client({
5  intents: [
6    GatewayIntentBits.Guilds,
7    GatewayIntentBits.GuildMessages,
8    GatewayIntentBits.MessageContent
9  ]
10});
11
12const agent = new MyAgent({
13  apiKey: process.env.ANTHROPIC_API_KEY
14});
15
16// Store sessions per channel
17const sessions = new Map<string, string>();
18
19client.on('messageCreate', async (message) => {
20  if (message.author.bot) return;
21  if (!message.content.startsWith('!agent')) return;
22
23  const query = message.content.slice(7).trim();
24  const sessionId = sessions.get(message.channelId) || message.channelId;
25
26  try {
27    await message.channel.sendTyping();
28
29    const response = await agent.query(query, { sessionId });
30
31    // Discord has a 2000 character limit
32    if (response.length > 2000) {
33      const chunks = response.match(/.{1,2000}/g) || [];
34      for (const chunk of chunks) {
35        await message.reply(chunk);
36      }
37    } else {
38      await message.reply(response);
39    }
40  } catch (error) {
41    await message.reply('Sorry, I encountered an error.');
42  }
43});
44
45client.login(process.env.DISCORD_TOKEN);

Slack Bot Integration

Create a Slack bot using Bolt:

src/slack-bot.ts
1import { App } from '@slack/bolt';
2import { MyAgent } from './agent';
3
4const app = new App({
5  token: process.env.SLACK_BOT_TOKEN,
6  signingSecret: process.env.SLACK_SIGNING_SECRET
7});
8
9const agent = new MyAgent({
10  apiKey: process.env.ANTHROPIC_API_KEY
11});
12
13// Respond to mentions
14app.event('app_mention', async ({ event, say }) => {
15  const query = event.text.replace(/<@[^>]+>/g, '').trim();
16
17  try {
18    const response = await agent.query(query, {
19      sessionId: event.channel
20    });
21
22    await say({
23      text: response,
24      thread_ts: event.thread_ts || event.ts
25    });
26  } catch (error) {
27    await say('Sorry, I encountered an error.');
28  }
29});
30
31// Respond to slash commands
32app.command('/agent', async ({ command, ack, respond }) => {
33  await ack();
34
35  const response = await agent.query(command.text, {
36    sessionId: command.channel_id
37  });
38
39  await respond(response);
40});
41
42app.start(process.env.PORT || 3000);

Webhook Integration

Trigger agent actions via webhooks:

1import express from 'express';
2import { MyAgent } from './agent';
3
4const app = express();
5app.use(express.json());
6
7const agent = new MyAgent({
8  apiKey: process.env.ANTHROPIC_API_KEY
9});
10
11// GitHub webhook handler
12app.post('/webhook/github', async (req, res) => {
13  const event = req.headers['x-github-event'];
14  const payload = req.body;
15
16  if (event === 'pull_request' && payload.action === 'opened') {
17    const prNumber = payload.number;
18    const prTitle = payload.pull_request.title;
19
20    const response = await agent.query(
21      `Review PR #${prNumber}: ${prTitle}`
22    );
23
24    // Post review as comment (implement as needed)
25    console.log('Review:', response);
26  }
27
28  res.status(200).send('OK');
29});

CI/CD Integration

Run agent as part of CI/CD pipeline:

.github/workflows/agent-review.yml
1name: Agent Review
2
3on:
4  pull_request:
5    types: [opened, synchronize]
6
7jobs:
8  review:
9    runs-on: ubuntu-latest
10    steps:
11      - uses: actions/checkout@v4
12        with:
13          fetch-depth: 0
14
15      - uses: actions/setup-node@v4
16        with:
17          node-version: '20'
18
19      - name: Install agent
20        run: |
21          cd my-agent
22          npm install
23          npm run build
24
25      - name: Run review
26        env:
27          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
28        run: |
29          cd my-agent
30          node dist/cli.js --query "Review the changes in this PR"

Best Practices

Session Management

Use session IDs to maintain conversation context:

  • Generate unique session IDs per user/channel
  • Store session state for continuity
  • Clean up old sessions periodically

Error Handling

Always handle errors gracefully:

  • Catch and log exceptions
  • Return user-friendly error messages
  • Implement retry logic for transient failures

Rate Limiting

Protect against abuse:

  • Implement per-user rate limits
  • Queue requests during high load
  • Monitor API usage and costs