This demo showcases how action context can provide useful "priming" for a prompt as well as help you secure tool calls and avoid security issues when calling the LLM. When you choose a user above, information about the user is added to the action context which is included in the system prompt that drives the chat as well as the tools that are called.

Each user is in one or more groups. There is an upcomingEvents tool that will list upcoming events that the user can see (only public events and those of their group):

  • mammals: sloth, koala, and panda are members
  • slowpokes: sloth and turtle are members
  • bearish: koala and panda are members

Things to Try

  • Ask the bot "who am I?". Switch users and ask it again.
  • Ask the bot "what should I eat for dinner" as different users.
  • Ask the bot "any upcoming events with trivia?" and inspect the source of the result.
  • Ask the bot for upcoming events from a specific group while unauthenticated.
  • Ask the for upcoming events of a group of which your user is a member.
  • Ask the bot upcoming events of a group of which your user is not a member.

Things to Notice

  • Security through context. Because the action context is available to the tool and deterministic logic determines which events are returned to the user, there is no way to "trick" the LLM into disclosing information it shouldn't, even if you ask it explicitly for information from a group the current user cannot access.
  • Hidden tool usage. In this example, the model makes tool calls invisibly behind the scenes. For an example where tool calls are shown as custom UI, see the Tool Calling example.

Source Code

// api/route.ts

import { z } from "genkit";
// this example requires beta features
import { genkit } from "genkit/beta";

import { googleAI, gemini20Flash } from "@genkit-ai/googleai";

const ai = genkit({
  plugins: [googleAI()], // set the GOOGLE_API_KEY env variable
  model: gemini20Flash,
});

import genkitEndpoint from "@/lib/genkit-endpoint";
import { GROUPS, UPCOMING_EVENTS } from "../data";

const upcomingEvents = ai.defineTool(
  {
    name: "upcomingEvents",
    description:
      "list upcoming events available for the current user. groupId is optional -- the tool will return all available events if it is not provided",
    inputSchema: z.object({
      groupId: z
        .string()
        .optional()
        .describe(
          'restrict event lookup only to a specific group. use "*" to search for all groups'
        ),
    }),
  },
  async ({ groupId }, { context }) => {
    if (groupId && !context.auth)
      return { error: "The user needs to authenticate to see group events." };
    // return only public events for unauthenticated
    if (!context.auth) return UPCOMING_EVENTS.filter((e) => e.public);
    if (groupId && !GROUPS[groupId])
      return { error: `Group '${groupId}' does not exist.` };
    if (groupId && !GROUPS[groupId].includes(context.auth?.uid))
      return {
        error: `User '${context.auth?.uid}' is not a member of the group '${groupId}' and cannot send it messages.`,
      };
    return UPCOMING_EVENTS.filter(
      (e) => e.public || GROUPS[e.group!].includes(context.auth?.uid)
    ).filter((e) => !groupId || e.group === groupId);
  }
);

const SYSTEM_PROMPT = `You are a helpful assistant and animal nutrition expert. Use Markdown formatting when replying. When using tools, assume the user wants to look in all groups unless they specifically mention one.

Available Groups: ${Object.keys(GROUPS).join(", ")}`;

export const POST = genkitEndpoint(async ({ messages, prompt, context }) => {
  const chat = ai.chat({
    system: `${SYSTEM_PROMPT}\n\nUser Info: ${JSON.stringify(
      context?.auth || "Current user is unauthenticated."
    )}`,
    messages,
    tools: [upcomingEvents],
    context,
  });
  return chat.sendStream({ prompt });
});
// data.ts

export const ANIMAL_USERS = [
  {
    uid: "sloth",
    emoji: "🦥",
    name: "Sloth",
    favoriteFoods: ["Blueberries", "Leaves"],
  },
  {
    uid: "koala",
    emoji: "🐨",
    name: "Koala",
    favoriteFoods: ["Eucalyptus Leaves"],
  },
  {
    uid: "turtle",
    emoji: "🐢",
    name: "Turtle",
    favoriteFoods: ["Strawberries", "Crickets"],
  },
  { uid: "panda", emoji: "🐼", name: "Panda", favoriteFoods: ["Bamboo"] },
];

export const GROUPS = {
  mammals: ["sloth", "koala", "panda"],
  slowpokes: ["sloth", "turtle"],
  bearish: ["koala", "panda"],
} as Record<string, string[]>;

const TODAY = Date.now();
const DAYS = 60000 * 60 * 24;
function futureDate(n: number) {
  return new Date(TODAY + n * DAYS).toISOString().substring(0, 10);
}

export const UPCOMING_EVENTS = [
  {
    group: "bearish",
    name: "Roundtable: We aren't bears (or are we?)",
    date: futureDate(1),
  },
  { group: "slowpokes", name: "Extra slow dance party", date: futureDate(3) },
  {
    public: true,
    name: "Animals Unite (for bar trivia)!",
    date: futureDate(3),
  },
  {
    group: "mammals",
    name: "The fur we were, a retrospective.",
    date: futureDate(5),
  },
  {
    group: "mammals",
    name: "Mammal Movie Night: March of the Penguins",
    date: futureDate(7),
  },
  {
    group: "slowpokes",
    name: "Snail Mail Social",
    date: futureDate(9),
  },
  {
    public: true,
    name: "Inter-Species Field Day!",
    date: futureDate(11),
  },
  {
    group: "bearish",
    name: "Bear Market Analysis (and Honey Tasting)",
    date: futureDate(13),
  },
  {
    group: "mammals",
    name: "Fur and Feathers Fashion Show",
    date: futureDate(15),
  },
  {
    public: true,
    name: "Wildlife Photography Workshop",
    date: futureDate(17),
  },
  {
    group: "slowpokes",
    name: "Zen Garden Design Workshop",
    date: futureDate(19),
  },
  {
    group: "bearish",
    name: "Hibernation Preparation Seminar",
    date: futureDate(21),
  },
  {
    public: true,
    name: "Animal Talent Show",
    date: futureDate(23),
  },
  {
    group: "mammals",
    name: "The Great Mammal Migration Simulation",
    date: futureDate(25),
  },
];
Genkit by Example uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.