--- title: 'An agent that starts a workflow' description: 'An agent tool that kicks off a background workflow and returns straight away, plus the variant that waits for the workflow result.' position: 2 --- # An agent that starts a workflow > The agent owns the conversation and offloads the slow work. A tool > starts an `enrich-profile` workflow and returns right away, so the user does > not wait while the background job runs. Swap `start` for `startAndWait` when > the agent needs the result before it replies. The whole agent is a single `deep-agents/onboarder/index.ts` file. It builds on the [agent examples](/docs/examples/agents/plain-greeter) and the [workflow examples](/docs/examples/workflows/onboarding-pipeline), so both halves should look familiar. ```ts // deep-agents/onboarder/index.ts import { tool } from '@langchain/core/tools'; import { z } from 'zod'; import { defineDeepAgent } from '@stackbone/sdk/deep'; import { stackbone } from '@stackbone/sdk'; const enrichProfile = tool( async ({ userId }: { userId: string }) => { const handle = await stackbone.workflows.start('enrich-profile', { userId }); // `queued` means the workflow is serial and an earlier run holds the lock, // so there is no run id yet. It starts on its own when the lock frees. return JSON.stringify({ status: handle.status, runId: handle.runId ?? null }); }, { name: 'enrich_profile', description: 'Start background enrichment for a user profile.', schema: z.object({ userId: z.string() }), }, ); export default defineDeepAgent({ name: 'onboarding', model: 'openai/gpt-4o-mini', tools: [enrichProfile], }); ``` Its instruction — help new users get set up, call `enrich_profile` with the user's id and say the enrichment is running in the background — is a prompt in the catalogue keyed `onboarding`, written and published in Studio. See [Prompts](/docs/sdk/platform/prompts). `start` resolves as soon as the run is accepted, so the tool hands the model an acceptance status rather than the workflow's answer. See [serial execution](/docs/sdk/workflows/serial-execution#triggering-a-serial-workflow) for the `queued` case. If the agent needs the workflow's result before it replies, swap `start` for `startAndWait`. It suspends until the workflow finishes, then returns the output validated against the target's `outputSchema`: ```ts const profile = await stackbone.workflows.startAndWait<{ tier: string }>('enrich-profile', { userId, }); return JSON.stringify({ tier: profile.tier }); ``` Both live on the `stackbone.workflows` namespace. There is no top-level `startWorkflow` import to reach for. ## What's next - **[A workflow that delegates a turn to an agent](/docs/examples/workflow-agents/delegate-to-agent)**: the same two pieces, with the workflow in charge. - **[Draft with an agent, then gate the send on a human](/docs/examples/workflow-agents/draft-then-approve)**: an agent draft behind a human approval. - **[What is a workflow agent](/docs/sdk/workflow-agents/overview)**: the model behind this flow.