Skip to content

Accessing flows from the client

There are two primary ways to access Genkit flows from client-side applications:

  • Using a Genkit client library
  • Using the client SDK for your server platform (e.g., the Cloud Functions for Firebase callable function client SDK)

This guide covers the Genkit client libraries.

You can call your deployed flows using a Genkit client library. The libraries provide a type-safe way to interact with both non-streaming and streaming flows.

Learn about flows in “Defining AI workflows”.

For a non-streaming response, use the runFlow function (in JS) or await the action (in Dart). This is suitable for flows that return a single, complete output.

import { runFlow } from 'genkit/beta/client';
async function callHelloFlow() {
try {
const result = await runFlow({
url: 'http://127.0.0.1:3400/helloFlow', // Replace with your deployed flow's URL
input: { name: 'Genkit User' },
});
console.log('Non-streaming result:', result.greeting);
} catch (error) {
console.error('Error calling helloFlow:', error);
}
}
callHelloFlow();

For flows that are designed to stream responses (e.g., for real-time updates or long-running operations), use the streamFlow function (in JS) or the .stream() method (in Dart).

import { streamFlow } from 'genkit/beta/client';
async function streamHelloFlow() {
try {
const result = streamFlow({
url: 'http://127.0.0.1:3400/helloFlow', // Replace with your deployed flow's URL
input: { name: 'Streaming User' },
});
// Process the stream chunks as they arrive
for await (const chunk of result.stream) {
console.log('Stream chunk:', chunk);
}
// Get the final complete response
const finalOutput = await result.output;
console.log('Final streaming output:', finalOutput.greeting);
} catch (error) {
console.error('Error streaming helloFlow:', error);
}
}
streamHelloFlow();

You can also stream custom objects. For robust JSON serialization in Dart, it’s recommended to use a code generation library like json_serializable. In TypeScript, you can use standard interfaces to define the shape of your data.

// Define the shape of your data
interface StreamChunk {
content: string;
}
interface MyOutput {
reply: string;
}
// In your streaming call, the client will handle JSON parsing
async function streamCustomObjects() {
try {
const result = streamFlow<MyOutput, StreamChunk>({
url: 'http://localhost:3400/stream-process',
input: { message: 'Stream this data', count: 5 },
});
console.log('Streaming chunks:');
for await (const chunk of result.stream) {
console.log('Chunk:', chunk.content);
}
const finalResult = await result.output;
console.log('\nFinal Response:', finalResult.reply);
} catch (e) {
console.error('Error calling streaming flow:', e);
}
}

When interacting with Genkit models, you’ll often work with standardized data classes. The client libraries provide these classes for type-safe interaction.

import { streamFlow } from 'genkit/beta/client';
import type {
MessageData,
GenerateResponseChunkData,
GenerateResponseData,
} from 'genkit/model';
async function streamGenerate() {
try {
const result = streamFlow<GenerateResponseData, GenerateResponseChunkData>({
url: 'http://localhost:3400/generate',
input: {
role: 'user',
content: [{ text: 'hello' }],
} as MessageData,
});
console.log('Streaming chunks:');
for await (const chunk of result.stream) {
// Note: A chunk may have multiple parts, and not all parts are text.
console.log('Chunk:', chunk.content[0].text);
}
const finalResult = await result.output;
// Note: A response may have multiple candidates.
console.log(
'\nFinal Response:',
finalResult.message.content[0].text
);
} catch (e) {
console.error('Error calling streaming flow:', e);
}
}

If your deployed flow requires authentication, you can pass headers with your requests:

const result = await runFlow({
url: 'http://127.0.0.1:3400/helloFlow', // Replace with your deployed flow's URL
headers: {
Authorization: 'Bearer your-token-here', // Replace with your actual token
},
input: { name: 'Authenticated User' },
});

When deploying to Cloud Functions for Firebase

Section titled “When deploying to Cloud Functions for Firebase”

When deploying to Cloud Functions for Firebase, use the Firebase callable functions client library.

Detailed documentation can be found at https://firebase.google.com/docs/functions/callable?gen=2nd

Here’s a sample for the web:

// Get the callable by passing an initialized functions SDK.
const getForecast = httpsCallable(functions, 'getForecast');
// Call the function with the `.stream()` method to start streaming.
const { stream, data } = await getForecast.stream({
locations: favoriteLocations,
});
// The `stream` async iterable returned by `.stream()`
// will yield a new value every time the callable
// function calls `sendChunk()`.
for await (const forecastDataChunk of stream) {
// update the UI every time a new chunk is received
// from the callable function
updateUi(forecastDataChunk);
}
// The `data` promise resolves when the callable
// function completes.
const allWeatherForecasts = await data;
finalizeUi(allWeatherForecasts);

source