GuidesBackend and frontend integration

Accept image input and regenerate

Use this recipe when an Agent should interpret an image and an End-user may ask it to regenerate the stored response. Image input is a chat message part, not general-purpose file upload or Artifact ingestion.

Outcome

One image-bearing message creates a Session, then a verified assistant message ID triggers truncate-and-rerun in that same authorized Session. The replacement is proven by reading the stored transcript.

Before you begin

Create a backend SDK client and authorize the Agent and application chat as in Build a chat endpoint. Review Sessions and Turns, Generation and streaming, Files and outputs, and Security and credentials.

Send an image part

A submitted message must be a user UIMessage with a non-empty ID and only text or image file parts. An image part uses type: "file", a non-empty url, an image/... mediaType, and an optional non-empty filename. Other file media types and arbitrary file-operation input are rejected.

import { BlazingAgents, type UIMessage } from "@blazing-agents/sdk";
const client = new BlazingAgents({ apiKey: process.env.BLAZING_AGENTS_API_KEY! });
const message: UIMessage = { id: "image-question-1", role: "user", parts: [
  { type: "text", text: "Describe this image." },
  { type: "file", mediaType: "image/png", filename: "sample.png",
    url: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" },
] };
const first = await client.chat({ agentId, message, userId });
const sessionId = await first.sessionId;
for await (const _chunk of first.toUIMessageStream()) { /* drain */ }
const before = await client.sessions.messages(agentId, sessionId);
const original = before.data.find(item => item.role === "assistant");
if (!original) throw new Error("No stored assistant response");

const retry = await client.chat({ agentId, sessionId, message,
  trigger: "regenerate-message", messageId: original.id, userId });
for await (const _chunk of retry.toUIMessageStream()) { /* drain */ }
const after = await client.sessions.messages(agentId, sessionId);
const [retainedUser, replacement] = after.data;
const validBranch = await retry.sessionId === sessionId &&
  after.data.length === 2 && retainedUser?.id === message.id &&
  retainedUser?.role === "user" && replacement?.role === "assistant" &&
  replacement.id !== original.id &&
  !after.data.some(item => item.id === original.id);
if (!validBranch) {
  throw new Error("The response was not replaced in the same Session");
}

Store the response

Drain the first stream so a successful Turn can commit. Store the resolved sessionId in the authorized application chat, then read sessions.messages() to retain the stored assistant message ID. Message listing returns newest pages first but keeps messages chronological within each page.

Regenerate a response

Regeneration is valid only on the resume path. Send trigger: "regenerate-message" with the authorized sessionId, the original user message, and a messageId verified from that Session. When the ID names the assistant response, the platform truncates from that message onward, retains the preceding user message, and appends a new assistant response. Omitting messageId targets the latest assistant message.

Verify the transcript

The example requires the regeneration result to resolve the same sessionId. It also asserts that the original user message remains exactly once, the old assistant ID is absent, and a required replacement assistant appears after the user message. This verifies transcript state rather than only HTTP success.

Production notes

  • Validate media type, URL source, and application upload limits before constructing the message. The chat contract itself requires an image media type and non-empty URL but does not place arbitrary files in an attached Sandbox filesystem.
  • Authorize the Agent, Session, and target message in backend state. A messageId outside that Session returns not_found.
  • Truncation and replacement commit together only when regeneration succeeds. A failed or aborted regeneration leaves the previous transcript unchanged.
  • If you target a user message instead of its assistant response, truncation also removes that user event and the supplied message is appended again.

SDK and REST reference

On this page