Take the community feedback survey now.

Graham Carr
Sep 4, 2025
  32
(2 votes)

A day in the life of an Optimizely Developer - The Optimizely Opal Tools SDK: How to Extend Opal with Your Own Superpowers

If you’ve spent any time with Optimizely Opal—Optimizely’s cross‑platform AI assistant—you’ll know it can already plan, generate, analyze, and automate across Optimizely One. Under the hood, Opal orchestrates agents and tools to decide what to do next, and it even routes requests through Google Gemini so your data stays private.

The Opal Tools SDK is how you add your own capabilities to that ecosystem. In this post, I will cover what it is, how it works, and show quick starts in Python and C#.


What is the Opal Tools SDK?

At a high level, the Opal Tools SDK lets you publish HTTP‑addressable tools that Opal can discover and invoke—think “plugins” that Opal can call to fetch data, trigger workflows, or render interactive responses. Each tool self‑describes via a /discovery endpoint (so Opal knows the functions, parameters, and auth it supports) and exposes one or more execution endpoints for runtime calls.

  • C# SDK (NuGet): Provides attributes like [Tool] and [RequiresAuth], an AddOpalToolsService() extension to wire everything up in ASP.NET Core, and built‑in discovery output.
  • Python SDK (PyPI): Adds decorators for defining tools, automatically generates discovery, validates parameters, and includes helpers for authentication and interactive “Island” UI responses.
  • JavaScript/TypeScript: Community examples show tools implemented with the @optimizely-opal/opal-tools-sdk npm package and deployed to edge/serverless environments like Cloudflare Workers.

Why extend Opal? Because while Opal ships with a lot of built‑in tools across Optimizely One, the SDK lets you integrate proprietary APIs, automate domain‑specific workflows, and expose differentiated capabilities that fit your organization’s processes.


How Opal selects and uses tools

When a user asks for something, Opal enriches the prompt with workspace context, selects the best agent and supporting tools, calls an LLM to plan, and—if needed—invokes tools to act, then returns a result in chat. Your custom tools become first‑class citizens in that loop.


Quick start: C# (ASP.NET Core)

The .NET SDK targets .NET 6+ and uses attributes to mark tool methods and declare auth requirements.

        [Tool("cmp_campaigns", "Retrieves a list of campaigns")]
        public static async Task<object> GetCampaigns(GetCampaignListParameters parameters)
        {
            var service = GetCmpService();

            return await service.GetCampaigns(parameters);
        }

        [Tool("cmp_create_campaign", "Allows the user to create a campaign in CMP.")]
        public static async Task<object> CreateCampaign(CreateCampaignParameters parameters)
        {
            var service = GetCmpService();

            var result = await service.CreateCampaign(parameters.ToCreateCampaignModel());

            return (result is null) ?
                new { Success = false, Message = "Failed to create campaign. Please check the parameters and try again." } :
                new { Success = true, Event = result };
        }

        [Tool("cmp_create_task", "Allows the user to create a task in CMP.")]
        public static async Task<object> CreateTask(CreateTaskParameters parameters)
        {
            var service = GetCmpService();

            var result = await service.CreateTask(parameters.ToCreateTaskModel());

            return (result is null) ?
                new { Success = false, Message = "Failed to create task. Please check the parameters and try again." } :
                new { Success = true, Event = result };
        }

Add [RequiresAuth("google","calendar")] for OAuth‑based flows.


Quick start: Python (FastAPI)

The Python package streamlines everything with a @tool decorator and a service that auto‑registers discovery at /discovery. You also get optional auth requirements and interactive Islands (lightweight UI components Opal can render to capture inputs and trigger follow‑up actions).

from fastapi import FastAPI
from pydantic import BaseModel
from opal_tools_sdk import ToolsService, tool

app = FastAPI()
tools_service = ToolsService(app)

class WeatherParams(BaseModel):
    location: str
    units: str = "metric"

@tool("get_weather", "Get current weather for a location")
async def get_weather(params: WeatherParams):
    return {"location": params.location, "temperature": 22, "units": params.units}
 
  • Discovery is exposed automatically at GET /discovery.
  • Add auth with @requires_auth(provider="google", scope_bundle="calendar", required=True).
  • Build interactive Islands with IslandConfig and IslandResponse for multi‑step flows.

JavaScript/TypeScript patterns

Examples show how to publish tools in TypeScript with Express or Workers, expose GET /discovery, and process POST calls for execution. Deployment tips include:

  • Keep /discovery public so Opal can read your capabilities.
  • Apply auth only to execution routes.
  • Handle CORS for serverless environments.

Authentication & security

Both SDKs let you express auth requirements per tool, so Opal can obtain user consent and pass provider‑scoped credentials to you at runtime. Your handler receives AuthData with provider identity and tokens you can use against Google, Microsoft, or other APIs—without building the consent UX yourself.


Interactive responses with “Islands”

A standout feature in the Python SDK is Islands—a way for your tool to return structured UI (fields, buttons) inside the chat, enabling multi‑step interactions without building a front end.


Architecture in practice

A typical tool service exposes:

  • GET /discovery → JSON describing functions, endpoints, and auth requirements.
  • POST /tools/<function> → Executes your business logic.

Opal discovers your service via the discovery URL you register in the Opal admin UI.


Real‑world use cases

  • Events Management
  • Internal system lookup (CMS, ERP, PIM)
  • Marketing ops automations
  • Experimentation helpers

Best practices

  • Keep /discovery public.
  • Validate parameters and return clear errors.
  • Handle CORS for edge deployments.
  • Design for chat UX with concise, markdown‑formatted results.

Final thoughts

The Opal Tools SDK gives you a straightforward way to meet your users where they already work—inside Opal—while enforcing your own security, governance, and business logic. Start small (one tool, one endpoint), keep discovery simple, and iterate toward richer, interactive flows.

Sep 04, 2025

Comments

Please login to comment.
Latest blogs
Building Faster Feedback Loops with Opal: Two Hackathon Projects

Two Opal Hackathon projects explored how to bridge data and action. Using the Optimizely.Opal.Tools SDK, we extended Opal with new tools, showing h...

Andy Blyth | Sep 3, 2025 |

Custom Deepl Glossary Translation in Optimizely CMS

Introduction in this post, I have created a custom DeepL glossary translation for specific words. For example, when translating from English to...

Deepmala S | Sep 3, 2025

Showing Unpublished Block Status in Optimizely CMS 12 ContentArea

Introduction One of the most common editor complaints in Optimizely CMS is that it’s not obvious when a block inside a ContentArea has unpublished...

Adnan Zameer | Sep 2, 2025 |

How to Show Unpublished Blocks in Page Preview (Optimizely CMS 12)

Introduction In this post, we’ll look at why Draft Blocks don’t show in Page Preview by default, and I'll show you a clean, drop-in solution to fix...

Adnan Zameer | Sep 1, 2025 |

A day in the life of an Optimizely Developer - We Hacked the Future: Netcel's Opal Hackathon Adventure

Ever wondered what happens when you mix  AI ,  creativity , and a dash of competitive spirit? Welcome to the  Opal Hackathon 2025 —where we rolled ...

Graham Carr | Aug 31, 2025