AI Plugin Development

An AuraBoot AI plugin is an ordinary plugin that contributes an agent definition, a tool set (commands and named queries), and the metadata required to make them usable from the agent runtime. This page walks through building one end to end.

Concept

AI plugins are not a separate plugin type. They are plugins that:

  • Register one or more agent definitions.
  • Contribute commands that opt into agent and/or MCP exposure.
  • Provide agent_hint metadata for every exposed command.
  • Optionally register named queries and a system prompt template.

The agent runtime discovers the contributions at startup the same way it discovers regular plugin resources.

When To Use

  • Building a domain-specific assistant ("supplier onboarding helper", "BOM auditor").
  • Packaging a reusable set of tools and prompts that a customer can install.
  • Extending an existing product with AI capabilities without forking the platform.

Plugin Layout

my-ai-plugin/
  plugin.json
  config/
    models/        # optional, if the plugin owns data models
    commands.json
    bindingRules.json     # required when commands declare handlers
    permissions.json
    agent-definitions.json
    namedQueries/
      bom-coverage.json
    i18n/
      en.json
      zh-CN.json
  backend/
    src/main/java/com/example/aiplugin/
      command/
        BomCoverageQueryHandler.java
      tool/
        BomAuditorAgentDef.java

Architecture

+--------------------------+      +-----------------------+
|  plugin.json + config    | ---> | Plugin loader (host)  |
+--------------------------+      +-----------+-----------+
                                              |
                              +---------------v---------------+
                              |  Metadata registry            |
                              |  - commands + bindingRules    |
                              |  - permissions                |
                              |  - agent-definitions          |
                              +---------------+---------------+
                                              |
                                              v
                              +---------------+---------------+
                              |  Agent runtime / MCP server   |
                              |  resolves tools at turn time  |
                              +-------------------------------+

Step 1: Register Permissions

Permission codes must follow {resource_type}.{resource_code}.{action} (all segments lowercase) and be declared in permissions.json. Referencing an unregistered code from commands.json or Java will fail validation.

[
  {
    "code": "bom.coverage.read",
    "name:zh-CN": "BOM 覆盖查看",
    "name:en": "Read BOM coverage stats",
    "description": "Read BOM coverage stats",
    "resourceType": "data",
    "module": "bom"
  },
  {
    "code": "bom.audit.execute",
    "name:zh-CN": "BOM 审计执行",
    "name:en": "Run BOM audit actions",
    "description": "Run BOM audit actions",
    "resourceType": "operation",
    "module": "bom"
  }
]

Step 2: Declare Commands and Binding Rules

Inline bindingRules inside commands.json are silently ignored by the importer. Always use a separate bindingRules.json registered in resourceDirs.

// commands.json (excerpt)
[
  {
    "code": "bom:query_coverage",
    "displayName:zh-CN": "查询 BOM 覆盖率",
    "displayName:en": "Query BOM Coverage",
    "type": "query",
    "modelCode": "bom_project",
    "handler": "bomCoverageQueryHandler",
    "inputFields": ["bom_project_id"],
    "permissions": ["bom.coverage.read"],
    "agent_hint": "Report BOM coverage for a project. Use when the user asks how complete a project's BOM is.",
    "cmd_risk_level": "L1"
  }
]
// bindingRules.json
[
  {
    "commandCode": "bom:query_coverage",
    "ruleType": "handler",
    "handlerClass": "bomCoverageQueryHandler",
    "sequence": 10,
    "enabled": true
  }
]

Step 3: Define the Agent

// config/agent-definitions.json
[
  {
    "agentCode": "bom_auditor",
    "name": "BOM Auditor",
    "description": "Reports BOM coverage and runs audit actions for projects the calling user owns.",
    "agentType": "reactive",
    "model": "deepseek-chat",
    "systemPrompt": "You are the BOM Auditor. Answer questions about BOM coverage and run audit actions only for projects the calling user owns. Always quote the projectId. Never invent line items.",
    "tools": [
      "cmd:bom:query_coverage",
      "cmd:bom:audit_execute"
    ],
    "skills": [
      "dsl.query",
      "dsl.command"
    ],
    "guardrails": {
      "evidenceFirst": true,
      "writePolicy": "Audit actions require explicit user confirmation."
    },
    "allowedOperations": ["query"],
    "status": "active",
    "visibility": "tenant"
  }
]

Register the file in plugin.json with "agentDefinitions": "config/agent-definitions.json". Tool references are distinguished by prefix: cmd: points to a command (e.g. cmd:bom:query_coverage) and nq: to a named query.

Step 4: Write the System Prompt

The system prompt is written directly into the agent definition's systemPrompt field (an inline string); no separate file is needed. State the agent's responsibility boundary, the fields it must quote, and the requirement to confirm before destructive actions:

You are the BOM Auditor. You may answer questions about BOM coverage and
run audit actions for projects the calling user owns. Always quote the
projectId you are working on. Never invent line items. If coverage data
is missing, ask the user to confirm before running an audit.

Step 5: Implement the Handler

The handler's bean name must match the handlerClass in bindingRules.json, and getHandlerName() must return the same value. The command's permissions are enforced uniformly by the pipeline from the permissions array in commands.json — no permission annotation is needed on the handler.

@Slf4j
@Component("bomCoverageQueryHandler")
@RequiredArgsConstructor
public class BomCoverageQueryHandler implements CommandHandler {

    private final BomCoverageService service;

    @Override
    public String getHandlerName() {
        return "bomCoverageQueryHandler";
    }

    @Override
    public Map<String, Object> execute(CommandHandlerContext context) {
        String projectId = (String) context.getPayload().get("bom_project_id");
        return service.coverageFor(projectId, context.getTenantId());
    }
}

Step 6: Package and Deploy

# Validate the plugin (catches unregistered handlers, raw labels, etc.)
aura plugin validate ./my-ai-plugin

# Build and package the plugin
aura plugin build ./my-ai-plugin

# Import the plugin config into a locally running host
aura plugin import ./my-ai-plugin

# Verify in the agent registry
aura ops agents show bom_auditor

After install, the agent is available to the Copilot panel, Aura Bot, ACP, and MCP. Tools resolve per turn against each caller's permissions.

Verify Checklist

  • permissions.json declares every code referenced by commands and Java.
  • bindingRules.json is a separate file (no inline binding rules in commands.json).
  • Every exposed command has a precise agent_hint.
  • User-facing strings use $i18n: keys, not raw Chinese or English literals.
  • aura plugin validate reports zero blockers.
  • After install, the agent appears in the registry and its tools resolve under a test user.

Related