Background Processes

Create and manage long-running background tasks in DAIN services

Overview

Background processes enable tools to start long-running tasks that continue executing after the initial response. This is ideal for operations like data analysis, file processing, or any task that may take significant time to complete.

A user can see the progress of a background process in the process viewer and in their dashboard, while continuing to interact with the assistant.

Process Store Configuration

Services using background processes must configure a process store for persistence. Two options are available:

import { 
  defineDAINService, 
  RedisProcessStore 
} from "@dainprotocol/service-sdk";

// Option 1: Redis Store (recommended for production)
const processStore = new RedisProcessStore(process.env.REDIS_URL);

// Option 2: Memory Store (default, for development)
const dainService = defineDAINService({
  // Memory store is used if processStore is not specified
  metadata: { /* ... */ }
});

// Using Redis Store
const dainService = defineDAINService({
  metadata: { /* ... */ },
  processStore: processStore  // Redis store for persistence
});

Creating a Process

Start a background process using the processes API:

handler: async (input, agentInfo, { app }) => {
  // Create a process with a descriptive name
  const processId = await app.processes!.createProcess(
    agentInfo,
    "one-time",
    "Data Analysis",
    "Analyzing dataset"
  );

  // Start background work
  (async () => {
    try {
      // Your long-running task
    } catch (error) {
      await app.processes!.failProcess(processId, error.message);
    }
  })();

  // Return immediately with process viewer
  return new DainResponse({
    text: "Analysis started",
    data: { processId },
    ui: { type: "processViewer", props: { processId } },
    processes: [processId]
  });
}

Updating Progress

Keep users informed about task progress:

await app.processes!.addUpdate(processId, {
  percentage: 20,
  text: "Processing data..."
});

Adding Results

Return UI components when the process completes:

import { CardListUIBuilder, ImageCardUIBuilder } from "@dainprotocol/utils";

// Create visualization UI
const visualizations = results.map(result => 
  new ImageCardUIBuilder(result.imageUrl)
    .title("Analysis Result")
    .description(result.description)
    .build()
);

// Add final results
await app.processes!.addResult(processId, {
  text: "Analysis complete",
  data: results,
  ui: new CardListUIBuilder()
    .title("Analysis Results")
    .description("Visualizations from your analysis")
    .addCards(visualizations)
    .build()
});

Example: Phone Call Service

Here's an example using Redis process store for a phone call service:

import { RedisProcessStore } from "@dainprotocol/service-sdk";

// Initialize Redis store
const processStore = new RedisProcessStore(process.env.REDIS_URL);

const makePhoneCallConfig: ToolConfig = {
  id: "make-phone-call",
  name: "Make Phone Call",
  handler: async ({ phoneNumber, goal }, agentInfo, { app }) => {
    // Create process
    const processId = await app.processes!.createProcess(
      agentInfo,
      "one-time",
      "Phone Call",
      `Calling ${phoneNumber}`
    );

    // Start call in background
    initiatePhoneCall(processId, app, phoneNumber, goal);

    return new DainResponse({
      text: "Initiating phone call",
      data: { processId },
      ui: { type: "processViewer", props: { processId } },
      processes: [processId]
    });
  }
};

const dainService = defineDAINService({
  metadata: { /* ... */ },
  processStore: processStore,  // Use Redis store
  tools: [makePhoneCallConfig]
});

Process States

A background process can be in one of these states:

  • running: Process is actively executing
  • completed: Process finished successfully
  • failed: Process encountered an error
  • cancelled: Process was manually stopped