Skip to content

Agents and workflows

This group covers what your Agent Service runs: how runs happen, the three kinds of agent (workflows, LLM agents, code agents), the building blocks they use, and how you ship them to a customer’s vault.

Your Agent Service is your account on Manykind, like a cloud account: it holds your agents and workflows, the cubby schemas, widgets, and datasets they use, and the members who work on them. Everything in it that runs on a vault’s data is an agent, and there are three kinds, side by side:

Kind What it is Where you build it
Workflow A typed graph of steps: triggers, models, agents, people, cubbies, connector actions. ROC Workflow Builder, or code with defineWorkflow
LLM agent Instructions, a model, tools, connections, and scopes; the model works the request through. ROC (New agent), or any A2A agent you run elsewhere
Code agent TypeScript engagement classes that react to events. Code, with @cef-ai/agent-sdk

All three share one path: you publish them to your Agent Service, deploy a version, and a vault owner connects them.

A workflow uses the other two as steps. Its Agent step asks an LLM agent or a code agent and waits for the answer. LLM agents and code agents are peers: either can answer a step, and either can also run on its own, on events in the vault.

In cef.config.ts the kind is kind: "workflow" | "internal" | "external": internal is a code agent, and external an A2A agent you run elsewhere. It is a classification for surfaces such as ROC; dispatch treats them the same.

Workflows

A workflow is an agent: same publish, deploy, and connect path, same agent id, same consent. What it adds:

  • A typed graph. Steps and the edges between them, with conditions on edges and typed inputs and outputs. The platform’s workflow runner walks the graph; you write no handlers.
  • A UI. Build and edit it in the ROC Workflow Builder, run it, and watch each run step by step.
  • Plug-ins as steps. Triggers, connectors, models, cubbies, widgets, people, LLM agents, and code agents are steps you drop into the graph.
Step family Step kinds Covered in
Start trigger (event, schedule, webhook, connector) Triggers
Think model, agent Model, Agent
People human People
Flow branch, join, split, aggregate Steps, Items
State cubbyQuery, cubbyExec Cubby steps
Memory remember, relate, recall Memory Bank
Act action (connector), publish Connector action
Shape transform, code, output Steps

The graph is data, not compiled code. Authored in code, it is baked into the manifest as a default; the Workflow Builder writes the deployed version. A workflow can start in git and be edited in ROC, and both are the same artifact.

cef.config.ts
import { defineAgent, defineWorkflow } from "@cef-ai/agent-sdk/config";
export default defineAgent({
id: "hiring",
version: "1.0.0",
agents: [
defineAgent({ id: "scorer", version: "1.0.0", entry: "./src/scorer.ts" }),
defineWorkflow({
id: "cv-review",
version: "1.0.0",
nodes: [
{ id: "start", kind: "trigger", emit: "candidate.review" },
{ id: "score", kind: "agent", use: "scorer" },
],
edges: [{ from: "start", to: "score" }],
}),
],
});

See Workflows overview and Workflows in code.

LLM agents

An LLM agent is defined, not programmed: you give it instructions, a model, the tools and connections it may use, and the vault scopes it declares. Create one in the Workflow Builder (Agent step → Choose an agent… → New agent) or on the Agents page; ROC creates it on the Agent Bridge and registers it with your Agent Service. An A2A agent you already run elsewhere joins the same way from its Agent Card.

Its answer is text; a later step reads fields from it only when the instructions or the step ask for JSON. See LLM agents and Bring your own (A2A).

Code agents

A code agent is TypeScript that reacts to events. Its building block is the engagement: a class marked @Engagement whose @OnEvent methods each handle one event type.

src/agent.ts
import { Engagement, OnEvent, type Context, type Event } from "@cef-ai/agent-sdk";
@Engagement({ id: "default", goal: "Reply to a user message" })
export default class EchoAgent {
@OnEvent("user_message")
async onMessage(event: Event<{ text: string }>, ctx: Context) {
await ctx.vault.publish("reply", { text: `you said: ${event.payload.text}` });
}
}
  • One engagement can own a whole flow. Several @OnEvent handlers on one class cover related event types.
  • Handlers are stateless. Nothing in memory survives to the next event. State lives in a cubby or the Memory Bank.
  • Selection. When an agent declares several engagements, the platform picks one per Job and pins it. @Condition (a CEL expression) filters, @Priority(n) picks the tier (lower wins), and @Weight splits within a tier. @Limit caps how often one is chosen, and @Params sets its parameter values.
  • Everything goes through ctx: ctx.models, ctx.cubby, ctx.memory, ctx.vault (publish events, read and write objects), ctx.settings, ctx.params, ctx.self, ctx.close.

See Write an agent and Runs and events.

How to choose

You want Build
A process people can read and change: steps, approvals, connector actions, model calls A workflow
Judgement a prompt can describe: classify, review, draft, decide with tools An LLM agent, used from a workflow’s Agent step
Custom logic a prompt cannot express: parsing, loops over APIs, a state machine A code agent, used from a workflow’s Agent step or on its own
To reuse an agent you already run elsewhere, in any language An LLM agent you bring over A2A

A common shape is all three: a workflow orchestrates, and its Agent steps call LLM agents and code agents for the parts that need them.