Inventory and ownership rules for shared Agent-Native workspace UI. Use before building app chrome, settings, navigation, sharing, collaboration, setup, history, comments, chat rails, agent UX, or repeated workspace behavior.
60
75%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.agents/skills/agent-native-toolkit/SKILL.mdUse this skill when deciding whether app chrome, settings, collaboration, sharing, navigation, organization, setup, history, comments, or agent UX should be built app-locally or moved into reusable framework/toolkit pieces.
Apps own domain models, domain actions, and product-specific workflows. The
framework and @agent-native/toolkit own repeated workspace behavior users
expect to work the same everywhere.
Move behavior into shared toolkit primitives when it is:
Keep behavior app-local when the abstraction would hide important domain language or make a simple app-specific workflow harder to understand.
The repeated app shell has two distinct navigation surfaces:
Chat just because
the app was scaffolded from the chat template.OrgSwitcher
in the sidebar footer) and from ⌘, (Ctrl+, elsewhere), which AppProviders
already binds. Keep the /settings route; don't add a Settings entry to
items, secondaryItems, or the footer.AgentSidebar owns contextual agent work. Domain buttons that call
sendToAgentChat should open it (openSidebar: true) so the user can see,
steer, and review the agent without losing the page they were using./ or /chat/* as the full-page chat surface when the starter provides
one. Put domain workflows on named routes and wire the shell's route checks,
navigation labels, and handoffs to those routes together.sendToAgentChat with bounded
context and openSidebar: true; local deterministic analysis should be
labeled as local, preview, or analyze. For original/generated review, stack
the source above the result by default and use side-by-side only for short,
highly scannable content.AgentSidebar must use one AgentKit controller and
transport. Core's AssistantChat export remains supported as an alias for
AgentKitAssistantChat; use AgentKit slots and registries for custom message
UI. Keep assistant-ui transcript/runtime imports inside the shared composer
integration; when linked dependencies need Vite aliases, resolve one
@agent-native/agentkit context and verify a real handoff.Contextual agent UI is not a reason to expose every option at once. Start with the domain task's primary action, reveal review or configuration only when the current state needs it, and let the sidebar carry conversational depth.
AgentKit context launchers use a shared Core capability contract. Design and
Slides consume get-agentkit-capabilities through
useAgentKitCapabilities: Core filters provider APIs by the current app's
exposed tool catalog and the same scoped connection grants or credential
resolver used by provider requests. Figma context readiness is checked against
its real Design processor. The shared hook also includes MCP servers only when
they are connected and expose tools visible to the current request. Keep source
retrieval (add-context) distinct from integration invocation intent
(invoke-integration), and revalidate an invocation when it is read for
submission. Keep only provider-specific pickers in app adapters; never
duplicate readiness checks, infer agent-tool readiness from messaging
connector status, or expose credential values. Keep a route to Integrations
settings available when a connection is missing.
Shared workspace behavior should be consistent without forcing every app into
the same visual skin. Keep shell and component tokens semantic, then let each
app declare a named direction in DESIGN.md before styling. A new app should
choose its palette family and composition from the product context, compare
nearby apps, and avoid inheriting their accent by default. Use the
frontend-design visual-direction reference for mode, palette, type, density,
shape, anti-references, and the distill / typeset / colorize / layout /
polish / audit review vocabulary.
Do not make warm beige plus terracotta the workspace fallback. Preserve a workspace-level brand when one exists; otherwise keep shared chrome neutral and allow app-owned accents to distinguish products while retaining accessible semantic states and the shared AgentSidebar contract.
Before creating an app-local version of repeated workspace or agent UI:
docs-search and
source-search.agent-native eject --list to see the version-matched units published
by the packages installed in this app.customizing-agent-native and configure, compose, or eject the
smallest unit instead of recreating shared behavior from memory.Use public package exports at runtime. Published source and ejection manifests are discovery and ownership-transfer mechanisms, not private runtime APIs.
Every app keeps an explicit design-system seam in app/design-system.ts using
defineDesignSystem from @agent-native/toolkit/design-system, and supplies it
to ToolkitProvider. The semantic contract contains:
ActionButton, IconButton, TextField, TextArea,
Spinner, Skeleton, Status, Surface, and AvatarTooltip, Menu, Popover, Dialog, Picker,
Checkbox, Switch, and TabsThese are semantic contracts, not styling contracts. An adapter may use
Tailwind/shadcn, MUI-style theme providers, React Aria, CSS modules, CSS-in-JS,
or another React design system. Do not assume CVA, utility classes, or even a
className; behavior adapters may supply their overlay and focus
implementation wholesale while honoring portal, focus-restoration, keyboard,
dismissal, ARIA, and z-index interoperability.
Pages, routes, and domain components import ordinary controls through the app's
local adapter layer, usually @/components/ui/*. They must not import
@agent-native/toolkit/ui/* directly. Toolkit feature exports are still the
right home for shared workspace behavior; their presentation flows through the
registered semantic components, feature controller, and product-level slots.
Customer adapter packages are normal npm packages imported explicitly by the
app. Never auto-detect them or load React components from JSON. Run the adapter
against @agent-native/toolkit/conformance in customer CI before adopting it.
Durable settings belong in Settings. The agent sidebar should not become a
second settings app; it can show contextual quick controls and deep links.
Settings has the same groups in every app, and page ids are stable URL segments
(/settings/<page>/<sub>):
profile, preferences, securityintegrations (integrations/builder), api-keysmodel, instructions, memory, skills, files, sub-agentsorg, members, usage, and for owners and admins auth,
apps, infra, auditapp (areas at app/<id>), notifications,
automations, channels (channels/<platform>), mcp, creative-contextlabs, whats-newLink with buildSettingsRoute(page, sub?, { anchor? }); old tab and section
ids resolve through the redirect table in
packages/core/src/navigation/settings-redirects.ts, the only place that maps
them. Account › Profile is the canonical profile surface (get-user-profile,
update-user-profile); don't build an app-local profile page.
When adding a new API key, OAuth grant, provider connection, model selector, app preference, notification preference, or usage/billing surface, find the page that owns that kind of setting first: provider keys go through the one provider dialog on Model, other keys on API keys, channels on Channels, and app-only preferences in the app's group. Only add sidebar UI when it is needed in the moment of agent use.
Settings has a group named after the app.
Core owns its pages: General, Notifications, Automations, Channels, MCP server,
Creative context, plus Labs and What's new in the footer. A template supplies
only its own content, through these SettingsTabsPage props:
generalGroups: the app's own SettingsGroups on its General page. Core puts
Agent › Default model above them (owners and admins change it; the agent
uses manage-agent-engine set-app-default) and This browser › Demo mode
below. Until a template passes it, today's general shows there.appAreas: [{ id, label, content, visible?, keywords?, searchEntries? }],
tabs on the General page routed /settings/app/<id>. Set visible: false
while the lab behind an area is off. A tab with
settingsPlacement: "app-area" in extraTabs works the same.notifications (plus notificationsSearchEntries): the Notifications page
shows only when this is passed.mcpAbout: the MCP server page's about line, naming what an MCP host can do
in this app.labs; What's new comes from whatsNewMarkdown, or from the
ChangelogSettingsCard passed as whatsNew.extraTabs item becomes its own page in the app's group. To swap a
core page for a variant, registerSettingsPages([{ ...corePage, component }])
at module scope (Dispatch's Members keeps its app-role column this way). To
add a group to one channel's page, registerChannelSettingsExtensions.The route needs a settings.$.tsx splat next to settings.tsx, and the layout
hides its own sidebar and header on Settings routes while the flag is on or
loading (isSettingsPathname), because the shell brings its own.
Search entries per area: each searchEntries item's hash is the row's
SettingsRow id, and a hit opens that area's tab and scrolls to the row. With
the flag off, the same props render as today's tabs, so a migrated template
works either way. Link with buildSettingsRoute("app", "<area>"), never a
hand-written path.
Gate UI on a lab with useLab(LAB_DEFINITION) rather than useLab(key): a
definition reads as its defaultEnabled until the server answers, while a bare
key reads as on.
Before building any setup, settings, credential, OAuth, or connection surface, search the workspace/provider connection catalog first. If the provider already has a reusable connection, use its catalog, app grant, and scoped credential resolver rather than registering a parallel secret. Only then classify fields that still need app-local setup by lifecycle and scope:
| Need | Default primitive |
|---|---|
| Deploy- or app-level configuration | Runtime configuration or deployment env vars |
| Existing workspace/provider connection | Workspace-connection catalog/grant plus resolveWorkspaceConnectionCredential(s)ForApp |
| App-local API/service key with no reusable connection | registerRequiredSecret({ kind: "api-key" }) and the vault |
| Authorization-code or refresh-token flow | kind: "oauth" with @agent-native/core/oauth-tokens |
| Account, customer, or other non-secret identifiers | Scoped connection metadata or app data |
| Provider-specific prerequisites, sequencing, or health | A thin app-local guide over the shared primitives |
Do not register every provider field as a generic secret, mark every field as required, or create a second credential-management surface. One logical connection should normally produce one onboarding outcome. A custom setup page is appropriate only when it adds domain-specific guidance or readiness checks; it should link to or call the shared settings, OAuth, and action surfaces rather than duplicating their storage or transport.
SettingsRow id so users find settings by name.ChatHistoryRail for the standard
five-item sidebar preview and a footer row with New chat followed by an
ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
actions.@agent-native/toolkit/data-grid. Apps provide rows, typed columns, editor
slots, selection and width state, persistence callbacks, and product-level
row/body slots. Keep database models, access checks, grouping, drag/drop,
and domain actions in the app adapter./agent surface (AgentTabsPage from
@agent-native/core/client) with Context, Files, Connections, Jobs, and
Access tabs plus a Personal/Organization scope toggle. The canonical home
for context transparency, MCP servers, A2A remote agents, recurring
jobs/automations, and external-client connect flows. See the agent-page
skill.When adding or refactoring one of these areas:
customizing-agent-native for the
configure → compose → eject → propose seam ladder.Read these alongside this skill when the work touches the specific area:
sharingreal-time-collabreal-time-syncclient-side-routingcontext-awarenessonboardingsecretsaudit-logobservabilityfrontend-designa941a2e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.