NestJS

05 Tools and Context

Pass NestJS auth, request data, and retrieval context into Anvia tools.

In NestJS, guards and services should own auth and data access. Pass request-local values into Anvia from controller or service methods.

1. Add A Request User Type

import type { Request } from "express";

export type AuthenticatedRequest = Request & {
  user: { id: string };
};

Use your existing guard to set request.user.

2. Build Request-Local Tools

import { createTool } from "@anvia/core";
import { z } from "zod";

export function createAccountTool(input: { userId: string }) {
  return createTool({
    name: "get_account_status",
    description: "Read the authenticated user's account status.",
    input: z.object({}),
    output: z.object({ plan: z.string(), openTickets: z.number() }),
    async execute() {
      return db.account.findStatus({ userId: input.userId });
    },
  });
}

3. Add A Request-Local Service Method

async runSupportForUser(input: { userId: string; message: string }) {
  return this.agent
    .prompt(input.message)
    .tool(createAccountTool({ userId: input.userId }))
    .context({ userId: input.userId })
    .send();
}

4. Call It From A Guarded Controller

import { Controller, Post, Req, UseGuards } from "@nestjs/common";
import type { AuthenticatedRequest } from "../auth/types";

@UseGuards(AuthGuard)
@Controller("api/support")
export class SupportController {
  @Post()
  async prompt(@Req() request: AuthenticatedRequest) {
    const response = await this.supportAgent.runSupportForUser({
      userId: request.user.id,
      message: request.body.message,
    });

    return { output: response.output };
  }
}

5. Add Retrieval Context

const documents = await this.knowledge.search({
  query: input.message,
  filter: { userId: input.userId },
  limit: 5,
});

return this.agent.prompt(input.message).documents(documents).send();

Next

Persist history in Persistence. Related guides: Runtime Context, Tool Handlers, and RAG Context.