Build a Plugin
Plugins let a Navigic agent call an external service through a reviewed,
versioned contract. A plugin is not loaded into Navigic as arbitrary code. It is
a service you operate, described by a manifest, and called through the
navigic.plugin/v1 protocol.
Current Availability
Plugin development is in managed preview. You can build a conforming plugin service and submit package evidence to Navigic for review. Self-serve marketplace discovery and dashboard installation for third-party plugins are not generally available yet.
If your goal is to connect a reviewed plugin to a workspace, start with Install a Plugin.
Managed-Preview Submission Flow
When Navigic has issued a developer API token for your account, you can submit
a plugin release from the public devkit. The CLI stores the token outside the
plugin repo and also accepts NAVIGIC_API_TOKEN and NAVIGIC_API_HOST.
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin login --token <developer-api-token>
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin publisher create example-inc \
--display-name "Example Inc." \
--website https://example.com \
--support-url https://example.com/support \
--contact-email [email protected]
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin publisher verify-domain example-inc \
--domain example.com \
--method dns_txt
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin package --out-dir dist --sbom
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin verify-package dist/navigic-plugin-package.json --strict-package
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin submit \
--publisher example-inc \
--package dist/navigic-plugin-package.json \
--plugin-url https://plugins.example.com/example-support/
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin status <submission-id> --watchBrowser login is not available in the current CLI slice. Domain verification may remain pending while Navigic review is managed-preview. A submitted package creates durable review evidence and a status object; it is not marketplace approval, public discovery, workspace install eligibility, or runtime operation granting.
If review requests changes, fix the plugin, package it again, and link the next submission to the prior review record:
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin package --out-dir dist --sbom
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin submit \
--publisher example-inc \
--package dist/navigic-plugin-package.json \
--resubmit <previous-submission-id>Scaffolded Development Loop
Navigic's public development loop is being introduced in stages. The first developer-facing milestone is scaffolding and local validation with the public devkit package. Use Node.js 22.14.0 or newer.
npm exec --yes --package @navigicai/plugin-devkit@latest -- navigic plugin init hello-action
cd hello-action
npm install --save-dev @navigicai/plugin-devkit@latest
npm test
npx navigic plugin validate contracts/navigic-plugin.manifest.json
npx navigic plugin package --out-dir dist --sbom
npx navigic plugin verify-package dist/navigic-plugin-package.jsonThis loop should let you build a conforming remote HTTP plugin without access to
private Navigic repositories. It validates the manifest, starts a local host
simulator, issues fake operation-scoped credential leases, and executes the
plugin through the same navigic.plugin/v1 envelope used by hosted workspaces.
To test a running plugin service locally, start the scaffolded plugin in one terminal:
npm run devThen start the Navigic local host simulator in a second terminal:
npx navigic plugin dev \
--plugin-url http://127.0.0.1:8787 \
--service-token local-dev-token \
--credential-lease-file fixtures/leases/local.jsonThe dev host prints a control token. Use that token from another terminal to execute an operation through the local host envelope:
npx navigic plugin execute create_ticket \
--input fixtures/execute/create-ticket.json \
--token <dev-host-control-token>The public package is @navigicai/plugin-devkit. Older commands or private
repo-local paths such as ../navigic-plugin-devkit/dist/cli.js are not required
for the public development loop.
Local success and CLI submission are not production approval. Production installation still requires Navigic review, verified publisher metadata, link and manifest checks, and a workspace install path enabled by Navigic.
What You Build
A remote HTTP plugin should expose these routes:
| Route | Purpose |
|---|---|
GET /.well-known/navigic-plugin.json | Returns the immutable plugin manifest. |
GET /health | Reports whether the plugin service is ready. |
POST /navigic/plugin/v1/execute | Executes one manifest operation for the Navigic host. |
Provider-facing routes, such as OAuth callbacks or webhooks, are plugin-specific.
For example, a Slack plugin may also expose /slack/oauth/callback and
/slack/events.
Build Steps
-
Choose the narrow job the plugin performs.
Start with one or two operations. Give each operation a stable
operationId, model-facingtoolName, JSON input schema, side effect, risk level, required scopes, approval default, and idempotency behavior. -
Publish a manifest.
The manifest declares the plugin's protocol version, package version, structured publisher, required license, trust links, release metadata, runtime routes, auth scheme, permissions, data use, operations, events, outbound domains, and redaction fields.
{ "apiVersion": "navigic.plugin/v1", "kind": "PluginManifest", "metadata": { "name": "example-support", "version": "0.1.0", "displayName": "Example Support", "description": "Create and read support tickets.", "license": "Proprietary", "publisher": { "id": "example-inc", "displayName": "Example Inc.", "type": "community_preview", "website": "https://example.com", "verifiedDomain": "example.com", "verificationStatus": "pending", "supportUrl": "https://example.com/support", "contactEmail": "[email protected]" } }, "links": { "homepageUrl": "https://example.com/navigic-plugin", "docsUrl": "https://example.com/navigic-plugin/docs", "installGuideUrl": "https://example.com/navigic-plugin/install", "configurationGuideUrl": "https://example.com/navigic-plugin/configure", "changelogUrl": "https://example.com/navigic-plugin/changelog", "supportUrl": "https://example.com/support", "privacyPolicyUrl": "https://example.com/privacy", "termsUrl": "https://example.com/terms", "securityUrl": "https://example.com/security", "repositoryUrl": "https://github.com/example/example-support-plugin" }, "release": { "version": "0.1.0", "releasedAt": "2026-07-22T00:00:00.000Z", "releaseNotes": "Initial preview release.", "breakingChanges": [], "migrationNotes": [] }, "hostCompatibility": { "protocolVersions": ["navigic.plugin/v1"], "navigicMinVersion": "0.1.0" }, "runtime": { "kind": "remote-http", "wellKnownPath": "/.well-known/navigic-plugin.json", "executePath": "/navigic/plugin/v1/execute", "healthPath": "/health" }, "auth": { "schemes": [ { "type": "service-token", "purpose": "Authenticate Navigic host-to-plugin execute requests." }, { "type": "api-key", "provider": "example-support", "location": "credentialLease", "scopes": ["tickets:write"], "purpose": "Use a short-lived operation-scoped provider credential lease.", "credentialLeaseFields": ["apiKey"] } ] }, "operations": [ { "operationId": "create_ticket", "toolName": "example_support__create_ticket", "displayName": "Create Ticket", "description": "Create a customer support ticket.", "inputSchema": { "type": "object", "properties": { "subject": { "type": "string" }, "body": { "type": "string" } }, "required": ["subject", "body"], "additionalProperties": false }, "outputSchema": { "type": "object" }, "sideEffect": "external-send", "risk": "external-write", "requiredScopes": ["tickets:write"], "approval": { "defaultMode": "ask" }, "idempotency": "required", "modelHints": { "readOnlyHint": false, "destructiveHint": false, "openWorldHint": true } } ], "permissions": { "providerScopes": [ { "provider": "example-support", "scope": "tickets:write", "purpose": "Let an approved agent create a ticket for handoff.", "dataAccess": ["ticket subject", "ticket body", "workspace metadata"], "operations": ["create_ticket"], "required": true, "risk": "external-write", "providerDocsUrl": "https://example.com/docs/scopes/tickets-write" } ], "outboundDomains": [ { "domain": "api.example.com", "purpose": "Create tickets through the Example Support API.", "dataCategories": ["ticket subject", "ticket body", "workspace metadata"] } ] }, "dataUse": { "collectedDataCategories": ["ticket subject", "ticket body", "workspace metadata"], "processedDataCategories": ["ticket subject", "ticket body"], "storedDataCategories": ["installation metadata", "activity and audit records"], "retention": "Retained as needed to operate the workspace and support audit or deletion requests.", "sharedWith": ["Example Support"], "humanAccess": "Example and Navigic support operators may inspect redacted operation metadata for support.", "modelExposure": "Ticket subject and body may be model-visible when the agent invokes the operation.", "deletionInstructions": "Revoke the plugin installation and request ticket deletion in Example Support." }, "outboundDomains": ["api.example.com"], "observability": { "redactFields": ["authorization", "access_token", "credentialLease"] } } -
Implement the execute endpoint.
Accept only authenticated host calls. Validate the request, enforce operation support, reject expired credential leases, require idempotency keys for write operations, and return a structured success or failure result.
{ "protocolVersion": "navigic.plugin/v1", "requestId": "req_123", "workspaceId": "workspace_123", "installationId": "install_123", "pluginId": "example-support", "pluginVersion": "0.1.0", "operationId": "create_ticket", "toolName": "example_support__create_ticket", "input": { "subject": "Billing question", "body": "The customer needs help with an invoice." }, "idempotencyKey": "workspace_123:req_123:create_ticket", "deadlineAt": "2026-07-21T20:00:00.000Z" } -
Keep credentials out of model-visible data.
Long-lived customer credentials belong in Navigic's host-side installation store or in the provider account you operate. Runtime calls should use a short-lived
credentialLeaseor a host service token, not raw customer secrets in prompts, transcripts, or logs. -
Test the plugin as a protocol boundary.
At minimum, test manifest validation, health, authentication failure, unknown operations, invalid input, expired leases, write idempotency, provider rate limits, and redacted logs.
Agent Enablement
An agent should grant specific plugin operations, not the whole provider. In an agent spec, the capability is operation-level:
capabilities:
pluginOperations:
- pluginId: example-support
operationId: create_ticket
versionRange: ^0.1.0The compiler lowers that into a bundle tool entry and a policy allowlist such as
example-support.create_ticket.