A complete, working implementation of this recipe — downloadable as a zip or browsable file by file. Generated by our build pipeline; tested with full coverage before publishing.
This recipe builds a secure, budget-controlled code execution API for SMB analysts. It combines Cohere’s language models for code safety classification, E2B’s sandboxed code interpreter for isolated execution, and REAA Technologies’ budget and confidence routing packages for spend enforcement. By the end, you’ll have a Next.js route handler at POST /api/code that classifies incoming code, checks budget, routes to an appropriate model, and executes it in an isolated sandbox.
Prerequisites
Node.js 22+ with pnpm 10
Next.js App Router project (created with npx create-next-app@latest --yes)
Expected output: pnpm installs all packages and updates package.json.
Step 2: Define request and response types
Every API surface starts with a contract. Create src/lib/types.ts to hold your Zod schemas and shared types. This gives you runtime validation on the way in and a single source of truth for everything downstream.
typescript
import { z } from "zod"export const CodeExecutionRequest = z.object({ code: z.string().min(1).max(50000), language: z.enum(["python", "sql"]), maxExecutionTimeMs: z.number().int().positive().optional().default(30000),})export const CodeExecutionResponse = z.object({ result: z.string().nullable(), stdout: z.string(), stderr: z.string(), error: z.string().nullable(), executionId: z.string(),})export type CodeExecutionRequestInput = z.infer<typeof CodeExecutionRequest>export type CodeExecutionResponseInput = z.infer<typeof CodeExecutionResponse>export type ClassificationLabels = "safe" | "dangerous" | "ambiguous"export interface BudgetState { spent: number remaining: number state: "Active" | "Warned" | "Degraded" | "Stopped" limit: number}export interface ModelRouteConfig { id: string provider: string costPerMillionInput: number costPerMillionOutput: number maxTokens: number capabilities: string[]}export interface CohereUsage { inputTokens: number outputTokens: number cost: number}export interface DangerousKeyword { label: string keywords: string[]}export const BudgetScope = { Org: "org", User: "user", Session: "session", Task: "task",} as const
Expected output:pnpm typecheck passes with no errors for this file.
Step 3: Load environment variables safely
Create src/lib/config.ts to load and validate the two required API keys. The function throws early with a descriptive message if a key is missing, so the server fails loudly rather than silently at the first request.
typescript
export interface Config { cohereApiKey: string e2bApiKey: string defaultModel: string fallbackModel: string maxExecutionTimeMs: number monthlyBudgetLimit: number}export function loadConfig(overrides?: Partial<Config>): Config { const cohereApiKey = overrides?.cohereApiKey ?? process.env.COHERE_API_KEY const e2bApiKey = overrides?.e2bApiKey ?? process.env.E2B_API_KEY if (!cohereApiKey) { throw new Error("COHERE_API_KEY is required") } if (!e2bApiKey) { throw new Error("E2B_API_KEY is required") } return { cohereApiKey, e2bApiKey, defaultModel: overrides?.defaultModel ?? "command-a-03-2025", fallbackModel: overrides?.fallbackModel ?? "command-a-03-2025", maxExecutionTimeMs: overrides?.maxExecutionTimeMs ?? 30000, monthlyBudgetLimit: overrides?.monthlyBudgetLimit ?? 5.0, }}
Expected output: Calling loadConfig() without COHERE_API_KEY set throws "COHERE_API_KEY is required".
Step 4: Wrap the Cohere SDK client
Create src/lib/cohere-client.ts. This adapter wraps CohereClientV2 from cohere-ai and exposes classify, chat, and chatStream. The null guard on response.message.content is essential: if Cohere returns an empty content block, you must check before accessing it, otherwise the SDK throws.
typescript
import { CohereClientV2, CohereError, CohereTimeoutError } from "cohere-ai"export class CohereAdapterError extends Error { constructor(message: string, public readonly statusCode?: number) { super(message) this.name = "CohereAdapterError" }}export class CohereAdapter { private cohere: CohereClientV2 constructor(apiKey: string) { this.cohere = new CohereClientV2({ token: apiKey }) } async classify(prompt: string, labels
Expected output:CohereAdapter.chat("hello") returns a string or throws CohereAdapterError. No silent null returns.
Step 5: Build a code safety classifier
Create src/lib/confidence-classifier.ts. This uses ConfidenceRouter from @reaatech/confidence-router with a KeywordClassifier from @reaatech/confidence-router-classifiers to gate dangerous imports before sandbox execution. The router’s routeThreshold: 0.8 and fallbackThreshold: 0.3 determine when to accept or reject a code snippet.
Create src/lib/sandbox-executor.ts. This uses Sandbox.create() from @e2b/code-interpreter to spin up an isolated environment. The key concern is defensive extraction of execution.text, execution.logs?.stdout, execution.logs?.stderr, and execution.error — the SDK returns these as potentially undefined, so each access is guarded. The sandbox is always torn down in the finally block, even if runCode throws.
Expected output: Running x = 1 via execute("x = 1", "python") returns an object with an executionId and either a result or an error.
Step 7: Implement the in-memory spend store
Create src/lib/spend-store.ts. This implements the SpendStore interface expected by BudgetController from @reaatech/agent-budget-engine. The null-safety concern here is guarding against entry.cost being null or undefined — when costs come back from an upstream API, they can be missing, so you treat them as 0 rather than letting NaN accumulate in the map.
typescript
import { SpendStore } from "@reaatech/agent-budget-spend-tracker"export class InMemorySpendStore extends SpendStore { private readonly spendMap = new Map<string, number>() override record(entry: { scopeType: string scopeKey: string cost: number requestId: string inputTokens: number outputTokens: number modelId: string provider: string timestamp: Date }): number { const key = `${entry.scopeType}:${entry.scopeKey}` const current = this.spendMap.get(key) ?? 0 const cost = typeof entry.cost === "number" && !isNaN(entry.cost) ? entry.cost : 0 this.spendMap.set(key, current + cost) return cost } override getSpend(scopeType: string, scopeKey: string): number { return this.spendMap.get(`${scopeType}:${scopeKey}`) ?? 0 } getSpent(scopeType: string, scopeKey: string): Promise<number> { return Promise.resolve(this.getSpend(scopeType, scopeKey)) } reset(scopeType: string, scopeKey: string): Promise<void> { this.spendMap.set(`${scopeType}:${scopeKey}`, 0) return Promise.resolve() }}
Expected output:record() accumulates spend correctly. Null cost is treated as 0 and does not corrupt the accumulated total.
Step 8: Wire up the cost controller
Create src/lib/cost-controller.ts. This combines BudgetController from @reaatech/agent-budget-engine with BudgetInterceptor from @reaatech/agent-budget-middleware. The checkBudget method calls interceptor.beforeStep() before any LLM call, and recordCost calls interceptor.afterStep() afterward. All numeric return values are null-guarded with ?? 0 — this prevents the "Cannot read properties of null (reading 'toFixed')" error that occurs when costs come back as null from the API.
typescript
import { BudgetController } from "@reaatech/agent-budget-engine"import { BudgetInterceptor } from "@reaatech/agent-budget-middleware"import type { BudgetScope } from "@reaatech/agent-budget-types"import { BudgetScope as BudgetScopeValues } from "./types.js"import { InMemorySpendStore } from "./spend-store.js"import type { BudgetState } from "./types.js"export class BudgetExceededError extends Error { remaining: number constructor(message: string, remaining: number) { super(message) this.name = "BudgetExceededError" this.remaining = remaining
Expected output:checkBudget(0.01, "command-a-03-2025") returns { allowed: true, ... } on a fresh budget. When the budget is exhausted, checkBudget returns { allowed: false, ... }.
Step 9: Build the model router with circuit breaker
Create src/lib/model-router.ts. This uses ModelDefinitionSchema from @reaatech/llm-router-core to validate model definitions at the boundary. The estimateCost method null-guards both inputTokens and outputTokens so that a null from the API response never reaches Math.round with an undefined value. The circuit breaker opens after 5 consecutive failures and resets on a successful call.
typescript
import { ModelDefinitionSchema } from "@reaatech/llm-router-core"import type { ModelDefinition, ModelCapability, CircuitBreakerState } from "@reaatech/llm-router-core"export interface BudgetConfig { dailyLimit: number alertThresholds: number[] hardLimit: number softLimit: number resetSchedule: string}const cohereModelDefs: ModelDefinition[] = [ ModelDefinitionSchema.parse({ id: "command-a-03-2025", provider: "cohere", costPerMillionInput: 0.50, costPerMillionOutput:
Expected output:estimateCost("command-a-03-2025", 1000, 500) returns 0.00125 (1,000 input tokens at $0.50/million plus 500 output tokens at $1.50/million). Null inputs return 0, not a crash.
Step 10: Add a safe usage extraction helper
Create src/lib/cohere-usage-tracker.ts. This helper extracts token usage from Cohere’s V2 response object. The "Cannot read properties of null (reading 'toFixed')" error occurs when the code tries to call .toFixed() on a null that came from chatResponse.usage?.input_tokens. This version checks isObject() at the top level, then checks isObject(usage) before accessing nested fields, and uses || 0 fallback on each numeric access.
Expected output:extractCohereUsage(null) returns { inputTokens: 0, outputTokens: 0, cost: 0 }. extractCohereUsage({ usage: null }) also returns the zero-cost tuple, not a crash.
Step 11: Export public types and wire the route handler
Export all public classes from src/index.ts:
typescript
export { CodeExecutionRequest, CodeExecutionResponse, BudgetScope,} from "./lib/types.js"export type { CodeExecutionRequestInput, CodeExecutionResponseInput, ClassificationLabels, BudgetState, ModelRouteConfig, CohereUsage, DangerousKeyword,} from "./lib/types.js"export { CohereAdapter } from "./lib/cohere-client.js"export { CodeSafetyClassifier } from "./lib/confidence-classifier.js"export { SandboxExecutor } from "./lib/sandbox-executor.js"export { CostController } from "./lib/cost-controller.js"export { ModelRouter } from "./lib/model-router.js"export { extractCohereUsage } from "./lib/cohere-usage-tracker.js"
Then create app/api/code/route.ts as the HTTP entry point. It validates the request, runs it through safety classification, checks budget, selects a model, executes the sandbox, records the cost, and returns the result. Each error type maps to its own status code and JSON body.
typescript
import { NextRequest, NextResponse } from "next/server"import { ZodError } from "zod"import { CodeExecutionRequest } from "../../../src/lib/types.js"import { loadConfig } from "../../../src/lib/config.js"import { CodeSafetyClassifier } from "../../../src/lib/confidence-classifier.js"import { CostController, BudgetExceededError } from "../../../src/lib/cost-controller.js"import { ModelRouter } from "../../../src/lib/model-router.js"import { SandboxExecutor, SandboxExecutorError } from "../../../src/lib/sandbox-executor.js"import { CohereAdapterError } from "../../../src/lib/cohere-client.js"import { extractCohereUsage } from "../../../src/lib/cohere-usage-tracker.js"export async function POST(req: NextRequest):
Expected output:POST /api/code with print("hello") returns 200 with execution result. POST /api/code with import os returns 403. POST /api/code on an exhausted budget returns 402. GET /api/code returns 200 with the current budget state.
Next steps
Add streaming responses with CohereAdapter.chatStream() for long-running code generation tasks
Implement per-user budgets with BudgetScope.User instead of BudgetScope.Org for multi-tenant scenarios
Add SQL dialect detection so language: "sql" queries run against a mock database in the sandbox
Integrate ModelRouter capability-based routing to select between Cohere models based on query complexity
Add request-level rate limiting with E2B sandbox timeouts to prevent runaway executions
:
string
[])
:
Promise
<{ predictions
:
Array
<{ label
:
string
; confidence
:
number
}> }> {
try {
const response = await this.cohere.chat({
model: "command-a-03-2025",
messages: [
{
role: "user",
content: `Classify the following code as one of these labels: ${labels.join(", ")}.\n\nCode:\n${prompt}\n\nReturn only a JSON object with a single key "label" containing the chosen label and a "confidence" key with a number between 0 and 1.`,