A hands-on guide walks through building a multi-turn AI agent using Genkit's Agents API (from the Firebase team). It covers defining an agent bound to a Gemini model, persisting sessions to Firestore via FirestoreSessionStore instead of in-memory or file-based storage, exposing the agent over HTTP with remoteAgent() for frontend use, running detached long-running turns that survive client disconnects via chat.detach() and getSnapshot polling, and gating risky tool calls (like record deletion) behind human-approved interrupts using defineInterrupt, respond(), and resume(). The result is an agent architecture that survives restarts, outlives browser connections, and enforces approval gates against persisted session history rather than trusting client claims.

16m read timeFrom blog.logrocket.com
Post cover image
Table of contents
Setting up the projectDefining and running an agent locallyOver 200k developers use LogRocket to create better digital experiencesPersisting sessions across restartsServing the agent over HTTPDetached turns for long-running workGating tool calls behind human approvalConclusion

Questions this post answers

How do I persist Genkit agent sessions in Firestore instead of local files?

Install @genkit-ai/google-cloud and replace FileSessionStore with FirestoreSessionStore in the agent's store option, using the same SessionStore interface. An empty FirestoreSessionStore() constructor connects to the (default) database and authenticates via a service account with the Cloud Datastore User role, set through GOOGLE_APPLICATION_CREDENTIALS. Sessions then span three collections: genkit-sessions, genkit-sessions-pointers, and genkit-sessions-shards. See how developers track emerging tools like Genkit's Agents API on daily.dev before adopting them.

How do detached turns work in Genkit's Agents API and do they survive the server restarting?

Detached turns, started with chat.detach(), let a long-running agent turn continue after the client disconnects, returning a DetachedTask with a snapshotId a client can poll via getSnapshot or reconnect to later. However, the turn continues inside the same server process that started it rather than moving to a separate worker, so that process must stay alive until the work finishes. Developers evaluating long-running AI agent architectures can follow tools like Genkit on daily.dev.

How do you make an AI agent pause for human approval before running a risky tool call?

Define the risky action with Genkit's defineInterrupt instead of a regular tool, giving it no implementation. When the model calls it, the turn pauses and the call appears in res.interrupts; a human then approves by calling interrupt.respond() with a result and passing it into chat.resume(), or forces a re-run with interrupt.restart(). The server validates the resume against the session's recorded history, so a client cannot fabricate an approval for a call that never happened. Teams designing human-in-the-loop AI agent flows can track patterns like this on daily.dev.

266 Impressions