@admin

API and usage

How admin exposes its capabilities — feature-gated HTTP routes and the one typed agent-core adapter — without shipping any tools or commands.

@neuralis/admin is unusual among the builtin packages: it ships no tools and no commands. Its entire programmatic surface is its set of HTTP routes — nineteen feature-gated route patterns — plus exactly one narrow typed adapter it uses to read from @neuralis/agent-core. Everything an administrator (or an admin skill, or the Admin widget) can do passes through that route surface; nothing about admin is hardcoded into the host.

If you are looking for the route-by-route table — every pattern, method, feature, and what it returns or mutates — that lives on Features and routes. This page is the higher-level shape: how the surface is organized, why it is routes rather than tools, and the single rule about how admin reaches agent-core.

No tools, no commands — routes are the API

Most packages put model-facing capabilities in tools/*.json (schema-first, dispatched to a handler) and operator shortcuts in commands/*.json. admin has neither folder. Its capabilities are privileged operations — read platform usage, edit a role, set a credential, reset the vector store — that should be exercised through authenticated, feature-gated, scope-aware HTTP requests, not offered to the model as free-floating tools.

The package therefore declares only routes (discovered from src/routes/*.ts), a singleton widget surface with its dock companion, six management skills, one workflow template, and the declarative rest — a privileged source instance, its uri-policy baselines, and two platform config settings. The six skills are the model-facing layer: an agent operates the platform by activating a skill whose scripts call these same routes with the per-stream session ticket — never by calling a bespoke admin tool. See Skills.

Every route module exports a pattern and a feature. The package route dispatcher checks that feature server-side against the caller's granted features before the handler runs; the general mechanism is described in Routes. Because there is no tool surface, the feature string on each route is the access boundary for that capability.

The route surface, grouped by capability

The admin routes fall into eleven capability groups. Each group is gated by a feature, and each route reads userId / projectId (and, where relevant, agentId) from the verified session — never from caller-supplied identity.

GroupRoutesGate
System overviewhealth, dashboard/stats, dashboard/usage, dashboard/codex-savings, packages, streams, projects / projects/:idproject.dashboard
Membersusersproject.members
Logslogs, logs/sourcesproject.audit (every platform-rooted source re-checks platform.audit in-handler: audit, routes, and a first-party package's own logs — system, sync, vector, and package/pkg with a bare slug; a project-installed _installed/<slug> log and the per-agent run log stay project-tier)
Platform auditauditplatform.audit (no default grant — the log carries no project id, so the module feature is platform-tier and there is no second in-handler gate)
Roles & sourcesconfig/roles, sourcesproject.roles / project.sources
Platform configconfig, vector/statusplatform.config / platform.vector
Package opscache/clear, rescanpackages.manage (live grant re-derived per call)
Credentialscredentials (read), credentials/scope-targets (the scope picker's target list), credentials/:id (write), credentials/use and credentials/use/:id (the platform-global use rules)project.credentials / platform.scope / project.credentials.write
Vector resetvector/resetplatform.vector.reset (no default grant)
Canvascanvas/graph, canvas/agent/:id, canvas/user/:idproject.canvas
Governancemembers-invite, projects-create, agents-assign, agents-admin/:idproject.members.invite / platform.projects.create / project.agents.assign / core.agents — every one of them stacks a second floor the feature alone does not satisfy: a role flag (canInvite, canManageRoles), an owner-strength check, or agent-core's own per-agent access check

The full table — with HTTP methods, exact return shapes, the in-route privilege escalations (for example dashboard/usage requiring platform.projects for scope=platform or platform.users for groupBy=user), and the mutation effects — is documented on Features and routes.

Feature-gated and scope-aware

Two independent dimensions govern every admin route:

  • Feature gating. The route's exported feature is checked before its handler runs. project.dashboard is granted to every role by default (so any member can open the system overview), but everything beyond the baseline overview must be granted explicitly. The owner role holds the '*' wildcard and passes every gate; the admin role holds every project-tier feature explicitly. No platform.* feature has a default grant. See Features and access.
  • Scope awareness (PROJECT vs PLATFORM). Most routes operate against the session's project and refuse to fan out across projects on a missing scope (deny-by-default — for example sources returns 400 rather than listing every project's sources). Crossing from the project tier to the platform tier is exactly what the platform.* features authorize, one power per id: all-projects listings (platform.projects), per-user spend (platform.users), the platform-global audit source (platform.audit), and acting on someone else's scope (platform.scope). A route can therefore serve a project-scoped answer to a baseline caller and a platform-wide answer to a caller who holds the matching id, from the same endpoint, degrading gracefully by privilege.

This mirrors the PROJECT / PLATFORM split in the Admin widget's own sidebar: the UI shows the platform section only to callers whose grants pass the platform-tier gates, but the client-side hiding is a convenience — the server-side feature check is always authoritative. See UI.

Reaching agent-core: one typed adapter, never bypassed

Several admin routes need data that lives in @neuralis/agent-core — active agent streams, connector status, the MCP server list, and usage aggregates for the dashboard charts. Per the platform's direct-internal-API rule, cross-package calls go through typed package APIs (getPackageApi()), never through internal MCP calls.

admin funnels its entire agent-core dependency through one small adapter, src/agentCoreApi.ts. It is a narrow structural mirror of just the members admin reads:

  • usageStore.summarizeProject(projectId) — all-time totals for a project.
  • usageStore.aggregate(filter) — the time-bucketed series behind the usage charts (the caller passes an explicit projectIds allow-list, so cross-project scope is always a deliberate decision, never implicit).
  • usageStore.projectSpan(projectId) — earliest/latest recorded event, used to size the all-time chart window dynamically.
  • listConnectorInstances() — connector status counts.
  • listMcpServers(session) — the MCP server list for the dashboard and canvas.
  • getActiveStreams() — running agent streams (every consumer filters by the session's projectId).
  • agentService.delete(...) — the agent delete behind DELETE agents-admin/:id. Access is re-checked inside agent-core against the caller's real session; the admin route adds transport and an audit row, never authority.
  • listCodexSubscriptions() — the connected Codex subscription snapshots (one per credential scope) behind the codex-savings card.
  • refreshCodexUsage(session) — one fail-soft live refresh of the caller's own Codex usage scope, derived from the verified session; it never impersonates another user or project, and a failed upstream read falls back to the stored snapshot rather than erroring.

Every route that reads agent-core runtime state — the dashboard, streams and canvas handlers and the agent delete — goes through getAgentCoreAdapter(); nothing reaches into agent-core internals directly.

Package maintenance uses ctx.hostPorts.packageMaintenance directly: the rescan and cache/clear routes pass the verified session's user/project ids, require packages.manage, and audit each operation. The host rechecks current package-management permission per call. A missing port returns503.

The silent-zero lesson

Every admin route and every admin test stub must use this adapter type. A 2026-06 dashboard regression made Usage, Connectors, MCP, and stream counts all silently read 0: the routes — and their test mocks — both invented methods (getUsageStore(), getConnectorRegistry(), getMcpClientManager()) that the real agent-core API never had, and optional chaining swallowed the mismatch into a misleading zero instead of an error. The fix was the single typed adapter, used everywhere, so a member-name drift fails loudly instead of degrading to zero. Do not add a second path to agent-core, and do not wrap the adapter calls in a catch that turns a genuine mismatch back into a zero.

Brain-core is reached the same way (through getPackageApi('@neuralis/brain-core')) for source health and the single validated upsertSourceConfig mutation point — the sources route never writes source JSON directly. The credential catalog uses the same narrow typed-shape form to ask agent-core which credential ids the loaded packages, skills and project channel connections declare — ids and labels only, never values.

Where admin sits among the three reach-paths

admin is an installed, first-party, in-process package, so its routes and handlers run as native Node and are dispatched directly — the richest of the three ways a package can reach the platform. The other two paths (a WASM-sandboxed project _packages/ drop, and context-only source markdown) expose narrower runtime surfaces. The package-system overview is the public owner of the full reach-path parity matrix; admin's route + adapter surface is the first-party, in-process row of it.

On this page