Web Frameworks
9 min readUpdated: October 2026

Integrate AI Agents into Next.js: Server Actions, Streaming & Route Handlers

Technical Review: Smoke Monkey Core Architecture Team
Tested on Node.js 18+ & BunTypeScript 5.x
Quick Answer & Executive Definition

Integrate AI Agents into Next.js: Server Actions, Streaming & Route Handlers: Designed as a zero-dependency, open-source TypeScript architecture under the MIT License with native Model Context Protocol (MCP) support and deterministic phase state machines.

Key Architectural Takeaways

Streaming Agent Events via Route Handler + SSE

Create a Next.js Route Handler that accepts a task instruction and streams agent events as Server-Sent Events:

app/api/agent/route.tstypescript
import { NextRequest } from 'next/server';
import { createAgent } from 'smoke-monkey-harness';
export const runtime = 'nodejs'; // Required for file system access
export async function POST(req: NextRequest) {
const { instruction, workspacePath } = await req.json();
const encoder = new TextEncoder();
const stream = new TransformStream();
const writer = stream.writable.getWriter();
const agent = createAgent({
provider: 'anthropic',
model: 'claude-3-7-sonnet',
workspacePath: workspacePath || process.cwd(),
autoApprove: true,
});
// Stream events to client via SSE
agent.on('model.streaming', (e) => {
writer.write(encoder.encode(`data: ${JSON.stringify({ type: 'chunk', text: e.data.chunk })}\n\n`));
});
agent.on('tool.started', (e) => {
writer.write(encoder.encode(`data: ${JSON.stringify({ type: 'tool', name: e.data.toolName })}\n\n`));
});
// Run agent and close stream when done
agent.run(instruction).then(() => {
writer.write(encoder.encode('data: {"type":"done"}\n\n'));
writer.close();
});
return new Response(stream.readable, {
headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },
});
}

useAgentStream React Hook

Create a custom hook to consume the SSE stream in your React components with live token streaming:

typescript
// hooks/useAgentStream.ts
export function useAgentStream() {
  const [output, setOutput] = useState('');
  const [isRunning, setIsRunning] = useState(false);

  const run = async (instruction: string) => {
    setIsRunning(true);
    setOutput('');
    const res = await fetch('/api/agent', {
      method: 'POST',
      body: JSON.stringify({ instruction }),
    });
    const reader = res.body!.getReader();
    const decoder = new TextDecoder();
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      const events = decoder.decode(value).split('\\
\\
');
      for (const event of events) {
        if (event.startsWith('data:')) {
          const data = JSON.parse(event.slice(5));
          if (data.type === 'chunk') setOutput((p) => p + data.text);
          if (data.type === 'done') setIsRunning(false);
        }
      }
    }
  };

  return { output, isRunning, run };
}
Google Search Questions & Answers

Frequently Asked Questions

Q:Can I use Smoke Monkey in Next.js Edge Runtime?

Edge Runtime lacks access to the Node.js file system APIs that Smoke Monkey's engineering tools require. Use the nodejs runtime for agent route handlers and edge runtime only for lightweight middleware.

Q:How do I prevent concurrent agent requests from conflicting on the same workspace?

Use a per-user or per-session workspacePath (e.g., /tmp/agent-workspaces/{userId}) and implement request queuing if multiple simultaneous agent runs are possible.

Related Alternatives & Comparisons

Build with Smoke Monkey Harness

Zero dependencies. 24 built-in tools. Human-in-the-loop safety. 100% open source under the MIT License.

npm install smoke-monkey-harness