Getting started with workflow agents

This page scaffolds a durable workflow already wired to an agent, then runs the whole thing locally. It builds on the agents and workflows getting-started guides, so skim those first if either building block is new.

1. Scaffold the hybrid

From inside a workspace, create an agent and a workflow that calls it in one step:

stackbone add workflow-agent lead-qualifier

This generates two things:

  • deep-agents/lead-qualifier/: a normal agent, the same shape as any other agent.
  • workflows/lead-qualifier.workflow.ts: a workflow whose step delegates a turn to that agent.

Both are fully offline: the pieces become members of the workspace stackbone init already linked, so no sign-in is required.

If you already have an agent and only want to add a workflow that calls it, wire them directly instead:

stackbone add workflow qualify-lead --calls lead-qualifier

2. Read the generated workflow

The generated workflow is a plain durable workflow whose one step runs a turn of the agent, in-process, and returns its reply:

workflows/lead-qualifier.workflow.ts
import { z } from '@stackbone/sdk';
import { streamDeepAgent } from '@stackbone/sdk/workflow';

export const inputSchema = z.object({
  message: z.string().describe('The message to hand to the lead-qualifier agent'),
});
export const outputSchema = z.object({ reply: z.string() });

export async function leadQualifierWorkflow(input: z.infer<typeof inputSchema>) {
  'use workflow';

  const reply = await askAgent(input.message); // step 1: delegate to lead-qualifier
  return { reply };
}

async function askAgent(message: string) {
  'use step';
  // In-process, no HTTP: the runtime resolves "lead-qualifier" in the
  // deep-agent registry, runs its graph, and returns the turn's final text.
  const { text } = await streamDeepAgent('lead-qualifier', message);
  return text;
}

The scaffold uses streamDeepAgent, the streaming twin of callDeepAgent. It runs the same in-process turn and returns the same durable { text }, but it also forwards the reply live onto the run's chat surface. That is what lets the Studio Playground serve this workflow as a token-by-token chat (a "workflow-agent") instead of a one-shot run. Swap it for callDeepAgent when nothing reads the stream live (for example, a later step parses structured data out of the reply). Both take the same arguments.

The workflow owns the fixed, auditable shape: a typed input, one durable step, a typed output. The agent owns the open-ended reply. Add more steps around askAgent to do deterministic work before or after the agent runs: validate the input, write the result to the database, or gate a side effect behind an approval.

3. Run it

Boot the local stack:

stackbone dev

stackbone dev discovers both the agent and the workflow, builds the agent in-process, and boots the durable runtime that serves the workflow alongside it. Then trigger a run, exactly like any other workflow:

stackbone workflows start lead-qualifier \
  --input '{"message":"We are a 200-person fintech evaluating your Pro plan."}'

The step delegates the message to the lead-qualifier agent and the run returns its reply. Watch the run and read its logs with:

stackbone runs list
stackbone runs get <runId>
stackbone logs tail --run <runId>

Because the delegation is a durable step, killing stackbone dev mid-run and starting it again resumes from the agent's recorded reply rather than asking it twice.

Since the generated step streams, you can also chat with this workflow. Open the Open Studio deeplink from the boot banner and pick the workflow in the Playground. Because it calls streamDeepAgent, the Playground routes it to the chat panel and paints the reply token by token instead of showing a one-shot run.

Where to go next

The platform for agent developers.Build, ship and observe agentsthat survive prod.

© 2026 · STACKBONEBUILT WITH ❤️ FROM CANADA AND SPAIN