DocsAI / Agents

Build AI applications with Deno

Design streaming, secret permissions, tools, RAG, and observability boundaries

Minimal security boundary

An AI service commonly listens, reads one provider key, and contacts one API:

deno run \
  --allow-net=0.0.0.0:8000,api.example.com:443 \
  --allow-env=MODEL_API_KEY \
  --no-prompt main.ts

Model names, API paths, and SDK methods change quickly. Query the provider's current official docs before implementation; never guess a default model in shared code.

Streaming proxy

Deno.serve(async (request) => {
  const upstream = await fetch("https://api.example.com/v1/responses", {
    method: "POST",
    headers: {
      authorization: `Bearer ${Deno.env.get("MODEL_API_KEY")}`,
      "content-type": "application/json",
    },
    body: await request.text(),
    signal: request.signal,
  });

  return new Response(upstream.body, {
    status: upstream.status,
    headers: { "content-type": upstream.headers.get("content-type") ?? "text/event-stream" },
  });
});

Production code must also limit body size, validate schema, set a timeout, map errors, and cancel upstream work when the client disconnects.

Tool calls

  • Map tool names to fixed functions; never interpolate model text into a shell.
  • Validate parameters with a schema and show impact before authorization.
  • Restrict file tools to a workspace and network tools to a host allowlist.
  • Separate reads from writes; require humans for deletion, publishing, payment, and production changes.
  • Log tool name, duration, result class, and request ID, but not secrets or full sensitive inputs.

RAG and evaluation

Keep source URL, version, update time, and access labels on chunks. Retrieved context is not authorization. Maintain a fixed evaluation set for refusal, prompt injection, timeouts, provider 429/5xx responses, and data leakage.

Official entry points: Deno AI and the Deno LLM tutorial.

Type to search all documentation.