Invect

Actions

Built-in actions, integration providers, and creating custom actions.

Actions are the building blocks of flows. Each action defines a node type — with a parameter schema, an execute function, and a provider grouping for the UI palette. Every action is automatically available as both a flow node and an agent tool.

Core Actions

The core provider contains the fundamental building blocks available in every flow:

  • Input / Output — Define the entry point and return values of a flow
  • Model — Call an LLM (OpenAI or Anthropic) with a prompt
  • If/Else — Conditional branching
  • JQ — Transform JSON data using JQ syntax
  • Template String — Generate text from Nunjucks templates

Integration Providers

Invect ships with actions for a growing set of third-party services. Each provider groups related actions under a common prefix (e.g. gmail.*, github.*). The full list of available providers and their actions is visible in the flow editor's node palette.

Current providers include: Gmail, Slack, GitHub, Google Drive, Google Docs, Google Sheets, Google Calendar, Linear, Microsoft 365, Postgres, and HTTP.

Most integration actions require a credential to authenticate with the external service.

Creating Custom Actions

You can define your own actions and register them with Invect:

my-action.ts
import { defineAction } from '@invect/core';
import { z } from 'zod';

export const myAction = defineAction({
  id: 'custom.my_action',
  name: 'My Custom Action',
  description: 'Does something specific to my app',
  provider: {
    id: 'custom',
    name: 'Custom',
    icon: 'Wrench',
  },
  params: {
    schema: z.object({
      input: z.string().describe('The input to process'),
    }),
    fields: [
      { name: 'input', label: 'Input', type: 'text', required: true },
    ],
  },
  async execute(params, context) {
    // Your custom logic here
    return { success: true, output: { processed: params.input } };
  },
});

Register it as a plugin or call registerAction after initialization:

import type { InvectPlugin } from '@invect/core';

export const myPlugin: InvectPlugin = {
  id: 'custom',
  actions: [myAction],
};

// Then in your config:
createInvectRouter({
  baseDatabaseConfig: { type: 'sqlite', connectionString: 'file:./dev.db', id: 'main' },
  plugins: [myPlugin],
});

Custom actions appear in the node palette under your chosen provider and are automatically available as agent tools.

Execution Context

The context object passed to execute provides:

PropertyDescription
context.incomingDataOutput from upstream nodes (keyed by node slug)
context.flowInputsThe original inputs passed to the flow run
context.credentialThe resolved credential (if credential.required is set)
context.loggerStructured logger scoped to this execution
context.functions.submitPromptSend a prompt to an LLM (with batch support)
context.functions.getCredentialFetch a credential by ID at runtime

Accessing Upstream Data

async execute(params, context) {
  // Access output from an upstream node with slug "fetch_user"
  const user = context.incomingData.fetch_user;
  return { success: true, output: { greeting: `Hello, ${user.name}` } };
}

Using a Credential

export const myAction = defineAction({
  id: 'my_provider.my_action',
  credential: {
    required: true,
    oauth2Provider: 'my_service', // or omit for API key credentials
  },
  async execute(params, context) {
    const token = context.credential?.config?.accessToken;
    const response = await fetch('https://api.example.com/data', {
      headers: { Authorization: `Bearer ${token}` },
    });
    return { success: true, output: await response.json() };
  },
});

For a more extensible approach to adding large sets of custom actions, see Plugins.