Back to Marketplace Guide

Creating Secure Tools

Build marketplace tools that execute on your own servers while keeping API keys and credentials private.

What are Secure Tools?

Secure tools are marketplace items that execute remotely on a provider's server instead of being downloaded as DLLs to consumer hosts. This model is ideal when your tool needs:

  • API keys or credentials — Users provide their own keys, which go directly to your server. Daisinet never stores them.
  • Proprietary logic — Your code runs on your infrastructure, protecting intellectual property.
  • External service access — Your server can call third-party APIs, databases, or other services directly.
  • Server-side state — Maintain user sessions, caches, or data that persists between invocations.

How It Works

The architecture uses an InstallId — an opaque identifier generated on purchase — for all provider-facing communication. No Daisinet account IDs are ever sent to providers.

  1. Purchase — When a user buys your tool, the ORC generates an InstallId and calls your /install endpoint to register the installation.
  2. Configure — The user enters their credentials in the Manager UI, which sends them directly to your server (not through the ORC) with the InstallId.
  3. Execute — During inference, the consumer host calls your /execute endpoint with a SessionId and parameters. Your server validates the session by calling back to the ORC, which returns the resolved InstallId and BundleInstallId.
  4. Uninstall — When a purchase is deactivated, the ORC calls your /uninstall endpoint so you can clean up stored data.
Why session-based validation? In the previous model, consumer hosts sent the InstallId directly, meaning any host that learned an InstallId could impersonate the installation. With session-based validation, the host only knows the ephemeral SessionId. The provider validates it with the ORC, which returns the real InstallId only to your authenticated server. This keeps the InstallId private between the ORC and the provider.

Step 1: Implement the Provider API

Your server must implement four POST endpoints:

POST /install ORC-originated

Called by the ORC when a user purchases your tool. Register the installation. For bundled tools, a shared bundleInstallId is included.

// Request
Headers: X-Daisi-Auth: {sharedSecret}
Body: {
  "installId": "inst-260215143022-abcdef",
  "toolId": "weather-lookup",
  "bundleInstallId": "binst-260215143022-shared"   // optional, present for bundled tools
}

// Response
{ "success": true }

POST /uninstall ORC-originated

Called by the ORC when a purchase is deactivated. Clean up stored data for this installation.

// Request
Headers: X-Daisi-Auth: {sharedSecret}
Body: { "installId": "inst-260215143022-abcdef" }

// Response
{ "success": true }

POST /configure Consumer-originated

Receives user setup data (API keys, credentials) directly from the Manager UI. Store these securely.

// Request (no X-Daisi-Auth header)
Body: {
  "installId": "inst-260215143022-abcdef",
  "toolId": "weather-lookup",
  "setupValues": { "apiKey": "sk-...", "region": "US" }
}

// Response
{ "success": true }

POST /execute Consumer-originated

Executes the tool with the given parameters. Called directly by consumer hosts with a sessionId instead of an installId. Your server must validate the session by calling the ORC before executing.

// Request from consumer host (no X-Daisi-Auth header)
Body: {
  "sessionId": "sess-260218120000-xyz789",
  "toolId": "weather-lookup",
  "parameters": [ { "name": "city", "value": "San Francisco" } ]
}

// Step 1: Provider validates session with ORC
POST {OrcValidationUrl}/api/secure-tools/validate
Headers: X-Daisi-Auth: {sharedSecret}
Body: { "sessionId": "sess-260218120000-xyz789", "toolId": "weather-lookup" }

// ORC response
{ "valid": true, "installId": "inst-260215143022-abcdef", "bundleInstallId": "binst-260215143022-shared" }

// Step 2: Provider executes using the resolved installId
// Response to consumer host
{
  "success": true,
  "output": "72 F, Sunny",
  "outputFormat": "plaintext",
  "outputMessage": "Current weather for San Francisco"
}

Auth model:

  • /install and /uninstall — Verify the X-Daisi-Auth header matches your shared secret. These come from the ORC.
  • /configure — Verify that the installId was registered via /install. No shared secret header is sent — the installId is an opaque, unguessable identifier that serves as a bearer token.
  • /execute — Receives a sessionId from the consumer host. Validate it by calling POST {OrcValidationUrl}/api/secure-tools/validate with your X-Daisi-Auth header. The ORC returns the resolved installId and bundleInstallId. Use the installId to look up stored configuration and execute the tool.

Step 2: Create the Marketplace Item

  1. In the DAISI Manager, navigate to Marketplace > Provider Dashboard > Create New Item.
  2. Set the Item Type to Host Tool.
  3. Enable the Secure Execution toggle.
  4. Fill in:
    • Endpoint URL — Your server's base URL (e.g. https://my-func.azurewebsites.net/api)
    • Auth Key — A shared secret the ORC will send as X-Daisi-Auth for install/uninstall
    • Tool ID — Unique identifier (e.g. my-weather-tool)
    • Tool Name — Display name for the AI (e.g. Weather Lookup)
    • Use Instructions — Natural language description of when/how the AI should use this tool
    • Tool Group — Category for filtering (e.g. Information Tools, Integration Tools)
    • Execution Cost — Optional credit cost per execution. If set, consumers are charged this amount each time the tool is invoked. The cost is snapshotted at execution time, so changing it later does not affect past records. Leave blank or set to 0 for no per-execution charge.
    • Call Parameters — Parameters the AI provides at execution time
    • Setup Parameters — Fields users fill in during configuration (API keys, regions, etc.)
  5. Submit for review. An admin will verify your endpoint is reachable and responds correctly.

Step 3: Reference Implementation

A reference Azure Functions implementation is provided in the daisi-tools-dotnet/SecureToolProvider directory. It demonstrates:

  • Installation registration and cleanup (/install, /uninstall)
  • Auth header verification for ORC-originated calls
  • InstallId validation for consumer-originated calls
  • Setup data storage and retrieval
  • Parameter handling and response formatting
  • Error handling for missing configuration or unknown installations

Clone the reference project and replace the echo logic with your actual tool implementation.

OAuth Integration

For tools that integrate with services like Office 365, Google, or X, use OAuth setup parameters instead of manual API key entry. The tool provider owns the entire OAuth lifecycle — Daisinet's role is limited to rendering a "Connect" button and checking connection status.

When to use OAuth vs API keys

  • API keys — When the user already has a key or can generate one from a service dashboard. Simpler to implement.
  • OAuth — When the service requires user consent via a browser flow (e.g. Microsoft Graph, Google APIs, X/Twitter API v2).

How to define an OAuth setup parameter

When creating your marketplace item, add a setup parameter with type oauth and fill in:

  • AuthUrl — Your provider's OAuth initiation endpoint (e.g. https://your-api.com/api/auth/start)
  • ServiceLabel — Display label shown on the Connect button (e.g. "Office 365", "Google")

The OAuth flow

[Configure Page]
  User clicks "Connect to [ServiceLabel]"
    --> Manager opens popup to provider's AuthUrl
    --> Provider redirects to external OAuth consent screen
    --> User authorizes
    --> External provider redirects to provider's /auth/callback
    --> Provider stores tokens, redirects popup to Daisinet's /marketplace/oauth-callback
    --> Popup shows "Connection Successful" and auto-closes
    --> Manager polls provider's /auth/status until connected
    --> Green "Connected" badge appears

Required provider endpoints

EndpointMethodPurpose
/auth/startGETInitiates OAuth flow. Receives installId, returnUrl, service as query params. Redirects to external consent screen.
/auth/callbackGETHandles OAuth callback from external provider. Exchanges code for tokens, stores them, redirects popup to returnUrl.
/auth/statusPOSTReturns connection status. Receives { installId, service }, returns { connected, serviceName, userLabel }.

Security notes

  • The provider registers their own OAuth app with external services and manages all client credentials.
  • Daisinet never sees OAuth tokens, client secrets, or refresh tokens.
  • The ORC has zero involvement in OAuth — no tokens, no client credentials, no refresh logic.
  • Hosts remain untrusted and never see tokens.

Bundle OAuth: Shared Authentication

When you publish a Plugin that bundles multiple secure tools from the same provider, users shouldn't have to OAuth-connect each tool separately. Daisinet supports BundleInstallId — a shared identifier that lets you key OAuth tokens at the bundle level.

How it works

  1. Purchase — When a user buys a Plugin with bundled secure tools, the ORC generates a shared BundleInstallId (prefixed binst-) in addition to each tool's own InstallId.
  2. Install notification — Your /install endpoint receives both installId and bundleInstallId. Store the mapping.
  3. OAuth — When keying OAuth tokens, use bundleInstallId (if present) instead of installId. This way, authenticating from any tool in the bundle makes all sibling tools show "Connected".
  4. Non-OAuth setup — API keys and other per-tool configuration still use the tool's own InstallId, keeping them independent.
// /install request for a bundled tool
{
  "installId": "inst-260215143022-abcdef",
  "toolId": "calendar-tool",
  "bundleInstallId": "binst-260215143022-shared"   // shared across bundle
}

// OAuth token keying
key = bundleInstallId ?? installId;
oauthTokens[$"{key}:google"] = tokens;

// Non-OAuth setup — always per-tool
setupData[installId] = { "apiKey": "sk-..." };

The reference implementation in daisi-tools-dotnet/SecureToolProvider demonstrates this pattern via the SetupStore class, which maintains a bundle map and resolves OAuth keys to the bundle level automatically.

Output Formats

The outputFormat field in the execute response determines how the output is rendered:

ValueDescription
plaintextPlain text (default)
jsonJSON data
markdownMarkdown formatted text
htmlHTML content
base64Base64 encoded binary data