Agents
A Stackbone agent is an in-process deep agent: it runs inside the runtime, with no subprocess and no port of its own. You author it as one file: its name, a model, and the tools it can call. Its instruction is not in the file. You write that in Studio. The runtime builds the agent once at boot and serves it over the standard OpenAI, Anthropic and AG-UI chat APIs. Any chat client or AG-UI frontend can talk to it with a base URL and a key.
Agents build on LangChain's deep-agent framework. Stackbone wraps it with a default model bridge, your org's injected model key, and a durable filesystem backed by your workspace's own storage. You write the agent itself.
The authoring model
- Authored as one file: an agent is
deep-agents/<name>/index.ts, which default-exportsdefineDeepAgent({ name, model, tools })from@stackbone/sdk/deep. There is no server to hand-roll and no per-agent manifest. - Discovery is by convention. Any folder under
deep-agents/that has anindex.tsis an agent. Drop one in andstackbone devpicks it up. The folder name is also the agent's identity: it is themodelvalue a chat client sends to talk to it, and it is thenameyou pass todefineDeepAgent. The two must match. - Its instruction is not in the file: you write the agent's persona in Studio, in the prompt catalogue, and the runtime reads it when it builds the graph. Changing the wording is an edit, not a deploy. An agent whose prompt is still empty runs and answers, it just has no persona yet. See where the instruction lives.
- Spoken over a standard wire: a request's
modelfield picks which agent answers, on the samePOST /openai/v1/chat/completionsandPOST /anthropic/v1/messagesendpoints every agent in the workspace shares. An AG-UI client reaches the same agent atPOST /agui/v1/agents/:name, with interrupts, frontend tools and shared state on top. See Agent protocol for the full contract. - Tools are plain LangChain tools. Each one is a function wrapped with
tool(...)from@langchain/core/tools, given a name, a description, and a Zod schema. The model decides when to call it from those three things. - Two tools come ready-made.
@stackbone/sdk/deepships two tool builders you do not have to write.connectorTool({ connector, operation })turns one operation of a connected provider into a tool (see Integrations), andbrowserTools()hands the agent a real Chromium (see Browser tools). - One ambient client covers the platform. Inside a tool's handler you reach it
through the shared
stackbonehandle (stackbone.config,.storage,.rag,.database, and more). You never construct a client or wire credentials. - The same object takes optional extras. Alongside
toolsyou can passsubagents(delegate a job to a specialist, like the built-in browser subagent),interruptOn(pause the run for a human before a named tool runs, see approvals) andeditableState(the state keys an AG-UI client is allowed to seed or edit).
// A deep agent is one file: deep-agents/greeter/index.ts.
import { tool } from '@langchain/core/tools';
import { z } from 'zod';
import { defineDeepAgent } from '@stackbone/sdk/deep';
import { stackbone } from '@stackbone/sdk';
const getGreeting = tool(
async () => {
const greeting = await stackbone.config.get('greeting');
return greeting.error ? 'Hello!' : String(greeting.data);
},
{
name: 'get_greeting',
description: 'Look up the configured greeting.',
schema: z.object({}),
},
);
export default defineDeepAgent({
// Must match the folder name: it is who this agent's prompts belong to.
name: 'greeter',
model: 'openai/gpt-4o-mini',
tools: [getGreeting],
});Where the instruction lives
The agent's instruction is a prompt in the catalogue, owned by this agent and keyed by its name. You write and edit it in Studio, on the agent's own Prompts panel, and publish the version you want live. The runtime reads the published text when it builds the graph, so a rebuild picks up the new wording with no code change.
Point the agent at a different key, or hand the text values it can render, by declaring them:
export default defineDeepAgent({
name: 'greeter',
model: 'openai/gpt-4o-mini',
instructions: { key: 'front_desk', variables: { tone: 'warm' } },
tools: [getGreeting],
});variables fills the {{tone}} placeholders the written text references. A
placeholder the text asks for and the declaration does not carry empties the
whole instruction, so declare every one the prompt uses.
Subagents work the same way. Each one names itself, and its brief is a prompt
under this agent keyed by the subagent's name unless you give it its own
instructions.
Files the agent writes
A deep agent has a filesystem of its own. It reads and writes paths like
/notes.md, and the runtime keeps them as objects in your workspace's
storage instead of on the container's disk. The files survive a restart, and
your own code lists them from the fs bucket with
stackbone.storage.from('fs').
The scope is the chat session. A file written during a session belongs to that session, so two conversations never read each other's notes. A turn that runs with no session in scope, such as a workflow step calling the agent, writes to a shared area the agent keeps across runs instead.
See stackbone.storage for the surface those objects
land in.
Where to go next
- Getting started: scaffold, write, and run your first agent.
- Examples: complete agents you can copy.
- Browser tools: give the agent a real Chromium to navigate, act on and extract from the web.
- Workflow agents: combine an agent with a durable workflow.
- Agent protocol: the full HTTP contract, the session key, tool approvals, and the AG-UI surface.