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.
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.
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
@OnEventhandlers 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@Weightsplits within a tier.@Limitcaps how often one is chosen, and@Paramssets 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.