Agents
In Polyant, an agent is the same thing as an instance: a fully configured AI assistant that lives in PostgreSQL and is brought to life by the Supervisor, a single reasoning loop that orchestrates every turn. There are no per-instance code branches and no specialized sub-agent classes — every instance, regardless of domain, is driven by the same supervisor wired against per-instance prompts, tools, and skills.
This page covers what the supervisor actually does on each turn, how the eight-section system prompt is assembled, how tools are presented to the LLM, and the two distinct delegation paths — spawnTask (ad-hoc sub-agent inside the same instance) versus agent-to-agent calls through the in-process agent channel adapter.
Instance equals agent
An instance is the unit of multi-tenancy and the unit of personality. A single engine process can host many instances side-by-side:
- Each has its own slug, name, provider (OpenAI, Anthropic, Bedrock), and model overrides.
- Each has its own row set in
instance_prompts,instance_tools,instance_skills,instance_secrets, andinstance_channels. - Each has its own memory partition (
memories.instance_id) and its own conversations. - Toggles like
memoryEnabled,langsmithEnabled, andauthEnabledare per-instance.
There is no shared global personality. The supervisor reads the active instance’s configuration on every turn (with a 30-second cache) and runs against that — so changes made in the admin panel take effect on the very next message.
The supervisor loop
The supervisor is a single agent, not a tree of specialised sub-agents. It runs in the standard tier with maxSteps = 15, meaning the LLM may chain up to fifteen reasoning/tool-call cycles before having to deliver a final response. The supervisor is invoked from the pipeline for every inbound user message, regardless of channel.
Each invocation receives:
- The instance’s system prompt (eight sections, see below).
- The last fifteen messages of conversation history.
- The current conversation summary (a rolling 2–3 sentence digest).
- The set of tools enabled for this instance (filtered via
instance_tools). - Optional sub-agent delegation via the built-in
spawnTasktool.
The tier hides the underlying model: components ask for fast, standard, or heavy — never gpt-4o or claude-sonnet-4-5. The supervisor always asks for standard; the instance’s chosen provider (and optionally a pinned model) decides what that resolves to. See AI Gateway for the tier-to-model tables and the per-instance override rules.
The eight prompt sections
An instance’s identity is composed of eight modular sections stored in instance_prompts (01-identity … 08-datetime). They are concatenated in order to build the system prompt, and they are the only runtime-editable surface for an agent’s behavior. The section keys are stable contract — they appear in the admin UI, the management API, and seed data — and new instances are seeded from packages/engine/src/instances/defaults.ts.
For the full table of section keys and roles, plus the optional contextual blocks appended at runtime (channel identity, conversation context, summary), see Prompt.
Delegation: two distinct mechanisms
Polyant ships two unrelated delegation paths — don’t conflate them:
spawnTask— ad-hoc sub-agent in the same instance. The supervisor’s built-inspawnTasktool creates an isolated sub-agent that runs against the same instance’s prompts/tools (minusspawnTaskitself, to prevent recursion). Useful for chunking a complex task in the current instance’s context.- Agent-to-agent via the
agentchannel. A separate, in-process channel adapter (packages/engine/src/channels/adapters/agent.adapter.ts) that lets instance A invoke instance B synchronously, with no HTTP/Slack/Telegram round-trip. The callee runs its own full pipeline (history, summary, supervisor, tools) and the reply is returned as a tool result on A’s side. This is wired through dedicated supervisor tooling, not throughspawnTask.
Agent-to-agent calls carry metadata (callerSlug, callerConversationId, depth, parentTraceId) so analytics and LangSmith traces stitch the child invocation back to its parent. Each call is gated by AGENT_CALL_TIMEOUT_MS (default 60000 ms, see packages/engine/src/config.ts) — a callee that does not return in time is aborted and the caller receives a timeout error.
See Channels for the channel-side perspective and Tools for how delegation tools are wired.
How it works
+----------------------------+
user message ->| Channel Adapter |
+--------------+-------------+
|
v
+----------------------------+
| Pipeline (handleMessage) |
| history + summary + ctx |
+--------------+-------------+
|
v
+----------------------------+
| Supervisor (tier=standard,
| maxSteps=15) |
| |
| system = sections |
| 01-identity |
| 02-soul |
| 03-tooling |
| 04-safety |
| 05-skills + {{list}} |
| 06-memory |
| 07-user-identity |
| 08-datetime |
| |
| +----------------------+ |
| | tool loop (<=15) | |
| | plan -> call -> ack| |
| | ... -> final text | |
| +----------------------+ |
+--------------+-------------+
|
v
+----------------------------+
| Outbound + fire-and-forget|
| (save msg, summary, mem) |
+----------------------------+Code reference
packages/engine/src/agents/supervisor/index.ts—supervise()/superviseStream(); tierstandard,maxSteps: 15.packages/engine/src/agents/supervisor/prompt.ts— System prompt builder that assembles the eight sections and renders the{{skillsList}}placeholder.packages/engine/src/instances/defaults.ts— Default content for every section, seeded on instance creation.packages/engine/src/instances/prompts.store.ts— Read/write API forinstance_promptsrows (60-second TTL cache).packages/engine/src/ai-gateway/config.ts— Tier-to-model mapping for OpenAI, Anthropic, and Bedrock.packages/engine/src/ai-gateway/index.ts—chat()/chatStream()entry points used by the supervisor.packages/engine/src/instances/config-resolver.ts— Resolves the active provider/model/secrets/channels for an instance at runtime.packages/engine/src/channels/adapters/agent.adapter.ts— In-process channel that powers agent-to-agent invocation.