Skip to content
Subako TypeScript SDK
Esc
navigateopen⌘Jpreview
On this page

Agents

Creating an agent and publishing the versions a session binds to.

An agent is a model, a prompt, and the things the model is allowed to reach. You publish it as a version, and a session binds to that version for its whole life. Publishing a new one later does not change a session already running.

These routes need a workspace credential, so they live on SubakoClient and not on SubakoSessionClient.

Creating one

const agent = await subako.agents.create({ name: "support" });

That gives you an agent with no versions yet. Nothing can run on it until you publish one.

await subako.agents.rename(agent.id, { name: "support-triage" });
await subako.agents.delete(agent.id);

const page = await subako.agents.list({ limit: 50 });

Publishing a version

The config is the version. You send the whole document, and what comes back is immutable.

const version = await subako.agents.publishVersion(agent.id, {
	model: {
		format: "anthropic",
		model: "claude-sonnet-5",
		max_tokens: 8192,
	},
	system_prompt: "You help people file support tickets.",
});

model picks the wire format and carries that format’s settings. There are two:

// Anthropic
{ format: "anthropic", model: "claude-sonnet-5", max_tokens: 8192, thinking: { budget_tokens: 4096 } }

// OpenAI Responses
{ format: "openai_responses", model: "gpt-5", max_tokens: 8192, context_window: 200_000, reasoning_effort: "medium" }

Which models you can name depends on the providers the workspace has. subako.modelProviders.list() tells you.

To see what has been published:

const versions = await subako.agents.listVersions(agent.id, { limit: 20 });

What the config grants

Beyond the model and the prompt, the config names what the agent may reach. Each grant gets a name that the model sees the thing under.

Skills

skills: [
	{ name: "refunds", skill_id: refund.skill_id, version: { type: "latest" } },
	{ name: "policy", skill_id: policy.skill_id, version: { type: "pinned", number: 3 } },
]

latest is resolved when each session is created, so a session started tomorrow may see a newer bundle. pinned never moves. See Skills.

MCP servers

mcp: [
	{
		name: "tickets",
		url: "https://mcp.example.com/tickets",
		default_policy: "require_approval",
		tools: [{ name: "search_tickets", policy: "allow" }],
	},
]

The broker serves the server at mcp:{name}. default_policy is allow, require_approval or deny, and it covers any tool not named in tools — including a tool the server adds after this version was published. A require_approval call shows up in the session log as an approval_requested event and the run waits; see Reading the log.

Credentials for these do not go in the config. They live in a vault, and the broker attaches them — see Vaults.

Sandboxes

sandboxes: [
	{
		name: "build",
		environment: { type: "platform", release: "2026" },
		default_policy: "allow",
	},
]

Each grant is a Linux instance the session owns, served at sandbox:{name} with an exec tool. Sandboxes covers reading them back.

Browser origins

This only matters if a browser talks to Subako directly. An agent answers no cross-origin request until you say which origins are allowed, so a page using SubakoSessionClient will fail its preflight until you do. A server-side job never sends an Origin and never needs this.

await subako.agents.setSecurity(agent.id, {
	allowed_origins: ["https://app.example.com"],
});

const security = await subako.agents.getSecurity(agent.id);

This is the piece people miss when a session works from their backend and not from their page.

Starting a session on it

const created = await subako.sessions.create({
	agent_id: agent.id,
	display_name: "support",
});

The session binds the agent’s current version at that moment. Quickstart shows what to do with the token that comes back.

Was this page helpful?