Skip to main content
Debug mode provides a development-friendly environment for testing your plugin with live connection to the Hub Server.

What is Debug Mode?

Debug mode is a special runtime mode that:
  • Connects directly to Hub Server for real-time testing
  • Dynamically registers your plugin without deployment
  • Authenticates via OneAuth to fetch author information
  • Generates definition.json for inspection
  • Provides verbose logging for troubleshooting

Enabling Debug Mode

Debug mode is enabled by default. Configure it via environment variables:
# .env
HUB_MODE=debug
HUB_WS_URL=wss://hub.atomemo.ai
HUB_DEBUG_API_KEY=your_api_key_here
DEBUG=true
NODE_ENV=development
HUB_MODE=debug is the default value, so you can omit it from .env.

Debug Mode Features

Dynamic Registration

Your plugin registers automatically when started:
1

Start your plugin

bun run index.ts
2

SDK connects to Hub Server

[2024-03-01 10:00:00] OPEN Connection established
[2024-03-01 10:00:01] JOINED Joined debug_plugin:my-plugin successfully
3

Plugin definition sent to Hub

channel.push("register_plugin", {
  name: "my-plugin",
  display_name: { en_US: "My Plugin" },
  credentials: [...],
  tools: [...],
  models: [...],
})
4

definition.json written to disk

{
  "name": "my-plugin",
  "author": "Your Name",
  "email": "[email protected]",
  "version": "0.1.0",
  "credentials": [...],
  "tools": [...],
  "models": [...]
}

Author Authentication

In debug mode, author information comes from OneAuth:
// SDK automatically fetches from OneAuth API
const deployment = env.HUB_WS_URL.includes("atomemo.ai") 
  ? "production" 
  : "staging"

const session = await getSession(deployment)
user = { 
  name: session.user.name, 
  email: session.user.email 
}
Requirements:
  • Valid HUB_DEBUG_API_KEY in environment
  • Active session in ~/.choiceform/atomemo.json
  • Network access to OneAuth API

Channel Naming

Debug mode uses a simple channel name:
const topic = `debug_plugin:${plugin.name}`
// Example: "debug_plugin:my-plugin"
Compare with release mode:
const topic = `release_plugin:${plugin.name}__${mode}__${version}`
// Example: "release_plugin:my-plugin__production__1.0.0"

Verbose Logging

With DEBUG=true, the SDK logs all events:
[2024-03-01 10:00:00] OPEN Connection established
[2024-03-01 10:00:01] JOINED Joined debug_plugin:my-plugin successfully
[2024-03-01 10:00:05] INVOKE_TOOL Received tool invocation
{
  request_id: "req_123",
  tool_name: "send-message",
  parameters: { channel: "#general", message: "Hello" }
}
[2024-03-01 10:00:06] INVOKE_TOOL_RESPONSE Tool invocation completed
{
  request_id: "req_123",
  data: { success: true, message_id: "msg_456" }
}

Testing Workflow

Testing Credentials

1

Add credential to plugin

plugin.addCredential({
  name: "api-key",
  display_name: { en_US: "API Key" },
  // ...
  authenticate: async ({ args }) => {
    console.log("Authenticating:", args.credential)
    // Validation logic
    return { valid: true }
  },
})
2

Start plugin in debug mode

bun run index.ts
3

Trigger authentication from Hub UI

The Hub Server will send a credential_auth_spec message:
[2024-03-01 10:01:00] CREDENTIAL_AUTH_SPEC Received auth request
Authenticating: { key: "test_key_123" }
4

Verify response

[2024-03-01 10:01:01] CREDENTIAL_AUTH_SPEC_RESPONSE Auth successful
{ valid: true }

Testing Tools

1

Add tool to plugin

plugin.addTool({
  name: "fetch-data",
  display_name: { en_US: "Fetch Data" },
  // ...
  invoke: async ({ args }) => {
    console.log("Tool invoked with:", args.parameters)
    const result = await fetchData(args.parameters)
    console.log("Returning:", result)
    return result
  },
})
2

Start plugin and watch logs

bun run index.ts
3

Invoke tool from Hub UI

[2024-03-01 10:02:00] INVOKE_TOOL Received invocation
Tool invoked with: { query: "test" }
Fetching data...
Returning: { count: 5, items: [...] }
[2024-03-01 10:02:01] INVOKE_TOOL_RESPONSE Sent response

Testing Models

Models are registered but not directly invoked:
1

Add model to plugin

plugin.addModel({
  name: "openai/gpt-4",
  display_name: { en_US: "GPT-4" },
  // ...
})
2

Inspect definition.json

{
  "models": [
    {
      "name": "openai/gpt-4",
      "display_name": { "en_US": "GPT-4" },
      "model_type": "llm",
      "input_modalities": ["text"],
      "output_modalities": ["text"]
    }
  ]
}
3

Verify in Hub UI

Check that the model appears in the model selection dropdown.

Inspecting definition.json

The generated definition.json shows your plugin’s serialized state:
{
  "name": "my-plugin",
  "display_name": { "en_US": "My Plugin" },
  "description": { "en_US": "A sample plugin" },
  "icon": "🔌",
  "author": "Your Name",
  "email": "[email protected]",
  "version": "0.1.0",
  "locales": ["en_US"],
  "credentials": [
    {
      "name": "api-key",
      "display_name": { "en_US": "API Key" },
      "description": { "en_US": "Your API key" },
      "icon": "🔑",
      "parameters": [
        {
          "name": "key",
          "display_name": { "en_US": "Key" },
          "type": "string",
          "required": true,
          "secret": true
        }
      ]
    }
  ],
  "tools": [
    {
      "name": "send-message",
      "display_name": { "en_US": "Send Message" },
      "description": { "en_US": "Send a message" },
      "icon": "📨",
      "parameters": [...],
      // Note: `invoke` function is NOT included
    }
  ],
  "models": [...]
}
Function properties like invoke and authenticate are excluded from serialization.

Debug API Key Management

Obtaining a Debug API Key

# Using Atomemo CLI
atomemo plugin refresh-key
This updates ~/.choiceform/atomemo.json:
{
  "auth": {
    "production": {
      "access_token": "your_access_token"
    }
  }
}

Key Expiration

Debug API keys expire after a period. If you see:
Error: Can't connect to the Plugin Hub server.

This is usually because the Debug API Key is missing or has expired.

Run `atomemo plugin refresh-key` to get a new key.
Refresh your key:
atomemo plugin refresh-key

Troubleshooting

Connection Issues

Problem: Plugin can’t connect to Hub Server Solutions:
echo $HUB_WS_URL
# Should be: wss://hub.atomemo.ai
# Refresh key
atomemo plugin refresh-key

# Verify in .env
grep HUB_DEBUG_API_KEY .env
curl -I https://hub.atomemo.ai
# Should return 200 OK
# .env
DEBUG=true

# Restart plugin and check logs
bun run index.ts

Authentication Errors

Problem: Failed to fetch user session Solutions:
# Check OneAuth config
cat ~/.choiceform/atomemo.json

# Verify access token exists
jq '.auth.production.access_token' ~/.choiceform/atomemo.json

# Re-authenticate
atomemo login

Registration Errors

Problem: Plugin definition rejected Check your definition:
// Missing required fields?
const plugin = await createPlugin({
  name: "my-plugin",
  display_name: { en_US: "My Plugin" },  // Required
  description: { en_US: "Description" }, // Required
  icon: "🔌",                             // Required
  locales: ["en_US"],                    // Required
})
Validate with Zod:
# Check definition.json
cat definition.json | jq .

# Look for Zod validation errors in logs
bun run index.ts 2>&1 | grep -i "validation"

Tool Invocation Errors

Problem: Tool fails when invoked Debug steps:
1

Add logging

invoke: async ({ args }) => {
  console.log("Args received:", JSON.stringify(args, null, 2))
  
  try {
    const result = await performAction(args.parameters)
    console.log("Success:", result)
    return result
  } catch (error) {
    console.error("Error:", error)
    throw error
  }
}
2

Check parameter types

// Validate parameters
if (typeof args.parameters.count !== "number") {
  throw new Error(`Expected number, got ${typeof args.parameters.count}`)
}
3

Verify credentials

const apiKey = args.credentials?.["api-key"]?.key

if (!apiKey) {
  console.error("Credentials:", args.credentials)
  throw new Error("API key not provided")
}

console.log("Using API key:", apiKey.slice(0, 10) + "...")
4

Test independently

// Create standalone test
async function testTool() {
  const result = await invoke({
    args: {
      parameters: { test: "value" },
      credentials: { "api-key": { key: "test_key" } },
    },
  })
  console.log("Test result:", result)
}

testTool()

Hot Reload

Debug mode supports hot reloading:
1

Make changes to your plugin

// Update tool implementation
plugin.addTool({
  name: "my-tool",
  invoke: async ({ args }) => {
    // New implementation
    return { updated: true }
  },
})
2

Stop the plugin

Press Ctrl+C to stop the running process.
3

Restart the plugin

bun run index.ts
4

Plugin re-registers automatically

[2024-03-01 10:05:00] OPEN Connection established
[2024-03-01 10:05:01] JOINED Re-joined debug_plugin:my-plugin
Use a process manager like nodemon or bun --watch for automatic restarts:
bun --watch index.ts

Best Practices

console.log(`[${new Date().toISOString()}] Tool invoked: ${args.parameters}`)
invoke: async ({ args }) => {
  // Test with missing parameters
  // Test with invalid credentials
  // Test with network failures
  // Test with rate limits
}
# Check generated definition
cat definition.json | jq '.tools[] | {name, parameters}'
Watch for errors in the Hub Server UI or logs.
# .env.example
HUB_MODE=debug
HUB_WS_URL=wss://hub.atomemo.ai
HUB_DEBUG_API_KEY=your_api_key_here
DEBUG=true
NODE_ENV=development
Commit .env.example to help other developers.

Transitioning to Release Mode

When ready for production:
1

Update environment variables

# .env
HUB_MODE=release
NODE_ENV=production
DEBUG=false
# Remove HUB_DEBUG_API_KEY
2

Ensure definition.json exists

# Should exist from debug mode
ls -la definition.json
3

Add author info to definition.json

{
  "author": "Your Name",
  "email": "[email protected]",
  "version": "1.0.0",
  // ...
}
4

Test in release mode

bun run index.ts
The plugin will:
  • Read definition.json for author info
  • Connect to release channel
  • Not send registration message
In release mode, changes to your plugin code won’t automatically update the Hub Server. You’ll need to redeploy or manually update the registration.

Next Steps

Environment Setup

Learn about all environment variables

Creating a Plugin

Build your first plugin

Build docs developers (and LLMs) love