@happyvertical/smrt-agents
Autonomous actors with scheduling, interests, dispatch, durable learning, principal execution, and safe agent-to-agent delegation.
What it gives you
Autonomous actors with scheduling, interests, dispatch, durable learning, principal execution, and safe agent-to-agent delegation.
- 01Recall-before and capture-after learning loops
- 02Multi-instance agents backed by durable personas
- 03Agent availability inherited down the tenant tree
- 04Principal-bounded worker orchestration with a maximum delegation depth
Dispatch and discovery are explicit contracts
DispatchBus emits and handles inter-agent messages, with matching dispatch CLI commands. An interest declared with interesting() discovers qualifying objects through its filter instead of relying on an unbounded scan.
Run tools as a bounded principal
executeAsPrincipal creates a PrincipalRun and checks assertToolAllowed and assertOperation before work proceeds. This is agent execution authority, distinct from smrt-users assertOperationPermission. A data surface can expose data.discover, data.inspect, and data.query through createDataSurfaceTools; report surfaces separately expose reports.query, refresh, drilldown, and export.
The host owns the process, not the agent
Signal handling is optional. An agent with manageProcessSignals set to true installs SIGTERM and SIGINT handlers. These handlers shut down and exit. The default false value registers nothing, which is suitable for a server or job runner. Do not enable this option for multiple agents unless the host coordinates shutdown. The first handler to finish exits the process.
Resolve tenant agents, do not list them
TenantAgent rows are explicit bindings between a tenant and an agent class. Call resolveForTenant on TenantAgentCollection to find what a tenant can run. Supply the tenant id and a function that returns ancestor ids. The resolver merges manifest permission defaults under explicit overrides and walks the tenant tree for inherited agents. Each result identifies its explicit or inherited source tenant. A plain list returns only explicit rows, without inheritance, merged permissions, or provenance.
How tenants nest →Delegation cannot widen authority
A worker invocation carries a delegation envelope with the acting user, tenant, allowed tools, correlation id, and depth. Depth is capped at three, and a requested principal that broadens the parent user, tenant, or on-behalf-of subject is rejected. Tool access is fail-closed: an execution whose allowed-tool list is missing or empty permits no tools at all.
Learning and delegation →Scheduling is declared here and run elsewhere
AgentSchedule records the cron expression, next and last run, concurrency ceiling, timeout, target method, and success and failure counts. The runner that starts these schedules is in smrt-jobs. Thus, an application selects its execution host instead of receiving a background worker with the agent model.
smrt-jobs →Agents can offer create entries
An agent class declares a literal static createEntries array, and the scanner captures it into the serialized agent. resolveAgentCreateEntries filters those entries by base path, access level, and capabilities, so a shell can offer them as create options.
Two Svelte entry points
The svelte subpath registers the schedule components with the shared module UI registry when it is imported. When a page only renders the admin shells, import from svelte/admin instead: it exposes the same admin components with no registration side effect.
Package UI
Components in this package
Import these public components directly. When the package also exports playground entries, the next tab renders its real components with package-owned example data.
Package previews
Try the working views
These previews are owned by the package and use its public components. Mock mode is intended for safe browsing; live mode appears only where the package supports it.
Generated interface
REST
The exact route set comes from each model's @smrt({ api }) policy
and the application manifest—not from a second controller definition.
GET /api/agents
GET /api/agents/:id
POST /api/agents
PATCH /api/agents/:idWhat stays consistent
- Tenant scope and operation permissions run before model access.
- OpenAPI and generated clients use the same manifest fields.
- Packages can expose read-only or custom action sets.
Generated interface
MCP
AI tools are generated from the methods you explicitly include. Their inputs are validated against the same model metadata used by REST and CLI.
agents_list({ where, limit, orderBy })
agents_get({ id })
agents_create({ data })
agents_update({ id, data })Agent-safe by construction
- Tool availability can be narrower than the HTTP API.
- Principal execution intersects RBAC, agent ceilings, and persona tools.
- Descriptions and schemas are emitted from source metadata.
Browser-native agent interface
WebMCP
The generated web definitions carry the same tool names, descriptions, and JSON Schema
inputs as MCP. smrt-web registers them with document.modelContext.
import { webMcpToolDefinitions } from '@happyvertical/smrt-virt-web';
import { registerWebMcpTools } from '@happyvertical/smrt-web';
// Omitting an exposure policy registers read-only tools only.
const dispose = registerWebMcpTools(webMcpToolDefinitions);The page keeps its security boundary
- Tools execute through generated REST fetchers as the signed-in page user.
- Authentication, tenant gates, permissions, and field policy stay server-side.
- Feature detection makes registration a safe no-op outside supported browsers.
Generated interface
CLI
The app CLI turns manifest resources into predictable operator commands while keeping package-specific actions close to their models.
smrt agents list --limit 25 --order-by created_at:desc
smrt agents get <id>
smrt agents create --from-file ./record.jsonMade for automation
- Machine-readable output and file-based input.
- The same include/exclude policy as other surfaces.
- Migration, introspection, dispatch, and knowledge commands stay in smrt-cli.