Actions

Purpose and Scope

Actions are Flue’s way to package finite, application-controlled operations around an agent harness. They are useful when a task should still use an agent’s model, sessions, sandbox, and configured capabilities, but the overall sequence should be owned by application code instead of improvised by the model. The guide defines an Action as reusable logic that orchestrates an agent harness in a deterministic, reliable way, especially for sensitive or reliability-critical work where inputs, context, outputs, and side effects should be explicit.

Sources: apps/docs/src/content/docs/guide/actions.md

An Action sits between a free-form tool call and a full workflow. Like a tool, it can be exposed to an agent as a model-callable capability with a name, description, and input schema. Like a workflow step, it can be bound to an agent and invoked as a durable operation whose run, result, and events are recorded under the workflow. This makes Actions a good fit for operations such as summarization, review, triage, enrichment, or controlled external work where the model can help, but the application controls how the work begins and ends.

Sources: apps/docs/src/content/docs/guide/actions.md

Relevant Source Files

  • apps/docs/src/content/docs/guide/actions.md — Defines the reader-facing Actions guide, including the defineAction() example, Action field meanings, workflow binding behavior, agent exposure behavior, and the note that src/actions/ is an organizational convention rather than a discovery convention.

Core Primitive: defineAction()

Create an Action with defineAction() from @flue/runtime. The example Action named summarize_document declares a model-facing name, a description, an input Valibot object schema, an output Valibot schema, and an async run() handler. Inside run(), the handler receives the invocation harness, parsed input, and a logger. It opens a session with harness.session(), prompts the configured agent, and returns data that matches the declared output schema.

Sources: apps/docs/src/content/docs/guide/actions.md

import { defineAction } from '@flue/runtime';
import * as v from 'valibot';
 
export const summarize = defineAction({
  name: 'summarize_document',
  description: 'Summarize a document clearly and concisely.',
  input: v.object({ text: v.string() }),
  output: v.object({ summary: v.string() }),
 
  async run({ harness, input, log }) {
    log.info('Summarizing document');
    const session = await harness.session();
    const response = await session.prompt(`Summarize this text:\n\n${input.text}`);
    return { summary: response.text };
  },
});

The important design point is that schemas belong to the Action. The input schema is a top-level Valibot object that Flue validates and transforms before run() starts. The optional output schema validates the returned value and snapshots it as JSON-compatible data. The name and description are model-facing metadata: they are what the model sees when the Action is exposed through an agent’s actions list, so they should describe when and why the capability should be used, not merely how the code is organized.

Sources: apps/docs/src/content/docs/guide/actions.md

Organizing and Importing Actions

The documentation uses src/actions/ as a practical folder convention for shared Actions, but Flue does not automatically discover that directory. An Action becomes available only when application code imports it into a workflow or an agent configuration. This distinction matters when debugging: placing a file under src/actions/ is not enough to register a capability, and removing an import is enough to make it unavailable to that workflow or agent even if the source file still exists.

Sources: apps/docs/src/content/docs/guide/actions.md

Use this explicit import model to keep capability boundaries clear. Shared Actions can live in one folder, be tested as ordinary TypeScript modules, and then be selectively attached where they make sense. A document editor agent might expose a summarization Action, while an internal workflow might bind the same Action for batch processing. Both use the same schema and handler, but they enter the runtime through different configuration surfaces.

Sources: apps/docs/src/content/docs/guide/actions.md

Use an Action in a Workflow

To run an Action as the main behavior of a workflow, bind it with defineWorkflow({ agent, action }). The guide shows a workflow that imports the summarize Action and pairs it with an agent configured with the model anthropic/claude-haiku-4-5. Each invocation runs the Action with that workflow’s configured agent, and the workflow records the run, result, and events. Because the Action owns its schemas and handler, the workflow does not repeat the input, output, or run definition.

Sources: apps/docs/src/content/docs/guide/actions.md

import { defineAgent, defineWorkflow } from '@flue/runtime';
import { summarize } from '../actions/summarize.ts';
 
export default defineWorkflow({
  agent: defineAgent(() => ({ model: 'anthropic/claude-haiku-4-5' })),
  action: summarize,
});

Binding an Action to a workflow is not the same as exposing it to the workflow’s model. The workflow can invoke the Action as its durable application operation, but the model does not automatically receive the Action as a callable tool. If the model should decide whether and when to call that same Action during a conversation, add it separately to the agent’s actions list. For behavior used by only one workflow, the guide points readers to the inline workflow form, where input, output, and run can be defined directly inside defineWorkflow().

Sources: apps/docs/src/content/docs/guide/actions.md

Give an Action to an Agent

Add an Action to an agent’s actions list when the model should be allowed to choose it. In that mode, Flue presents the Action as a framework-managed tool using its name, description, and input schema. When the model calls the Action, Flue runs it with an isolated child harness and returns the Action result to the conversation. This lets the model request a controlled operation while the Action handler still enforces application-defined structure and output.

Sources: apps/docs/src/content/docs/guide/actions.md

import { defineAgent } from '@flue/runtime';
import { summarize } from '../actions/summarize.ts';
 
export default defineAgent(() => ({
  model: 'anthropic/claude-sonnet-4-6',
  instructions: 'Help the user edit and understand their documents.',
  actions: [summarize],
}));

The child harness is intentionally scoped. It has independent sessions while sharing the parent agent’s configuration, sandbox, and filesystem. Its conversation records remain in the append-only agent-instance stream rather than being recursively deleted. This preserves traceability for model-initiated Action calls while preventing the Action from simply reentering the active parent session as if it were ordinary prompt text. Actions also share the model-facing namespace with custom and framework-provided tools, so active capabilities need distinct names.

Sources: apps/docs/src/content/docs/guide/actions.md

Compact Reference

ConceptSource-backed behavior
defineAction()Creates a reusable finite operation for an agent harness.
nameModel-facing name used when an Action is exposed to an agent.
descriptionHelps the model decide when to call the Action.
inputOptional top-level Valibot object schema validated and transformed before run().
outputOptional Valibot schema used to validate and snapshot returned JSON-compatible data.
run({ harness, input, log })Performs the operation, typically by opening sessions, using the configured sandbox, or calling other agent capabilities.
Workflow bindingdefineWorkflow({ agent, action }) runs the Action under the workflow and records its result and events.
Agent exposureactions: [summarize] makes the Action available as a framework-managed model-callable tool.

Practical Next Steps

Start by extracting any repeated, reliability-sensitive agent logic into a named Action with a clear Valibot input and output contract. Import it into a workflow when your application should invoke the operation directly, and add it to an agent’s actions list only when the model should decide to call it. If the operation is used by exactly one workflow, compare this pattern with inline workflow definitions before introducing a shared Action module. Read the Workflows and Building Agents pages next to decide which integration surface fits the task.

Sources: apps/docs/src/content/docs/guide/actions.md