// docs

Template System

Build reusable agent blueprints with HTML/CSS/JS interfaces, Python defaults, and prompt configurations.

Overview

πŸ‘‹ Just want your own agent?

Templates are for creators building reusable blueprints. If you just want an agent for yourself, you don't need to read this page β€” go pick a starting point and click "Use this template." This page explains what happens under the hood, and how to build your own blueprint from scratch.

AgentOp templates are versioned, reusable blueprints that define everything a browser AI agent needs: the HTML/CSS/JS interface that users interact with, the Python tool functions that execute in-browser via Pyodide (WebAssembly), the system and user prompt configuration, and the default Python packages to load. When someone creates an agent from a template, they receive a fully wired-up starting point β€” they only need to customise the Python logic and prompts for their specific use case.

This makes AgentOp templates a powerful accelerator for building browser-executable AI agents. Instead of writing HTML scaffolding, Pyodide bootstrapping, LangChain wiring, and wllama integration from scratch, you start from a working template and focus exclusively on the domain-specific Python code that makes your agent unique.

Template Components

1. Presentation Layer

  • HTML Code: Structure and layout of the agent interface
  • CSS Code: Styling and visual design
  • JavaScript Code: Client-side interactivity

2. Behavioral Defaults

  • Python Code: Default agent logic and tools
  • System Prompt: Agent personality and instructions
  • User Prompt Template: How to format user input
  • Few-Shot Examples: Example interactions
  • Prompt Variables: Configurable placeholders

3. Configuration

  • Default Packages: Python dependencies
  • Memory Settings: Conversation history configuration
  • Metadata: Name, description, tags, category

Creating a Template

Step 1: Navigate to Template Builder

Go to /templates/new/ to start creating a template.

Step 2: Fill Metadata

  • Name: Unique, descriptive name
  • Description: What agents built from this template will do
  • Category: chatbot, data-analysis, code-assistant, etc.
  • Tags: For discovery and organization

Step 3: Design the Interface

HTML Structure

Define the layout using template variables. Note the type="text/python" on the Python script tag β€” this tells the browser it is not JavaScript:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{agent_name}}</title>
    <style>{{css_code}}</style>
</head>
<body>
    <div class="container">
        <h1>{{agent_name}}</h1>
        <p class="description">{{description}}</p>

        <div id="chat-container">
            <div id="messages"></div>
            <input type="text" id="user-input" placeholder="Type a message...">
            <button id="send-btn">Send</button>
        </div>
    </div>

    <!-- Python code runs via Pyodide, not as native JS -->
    <script type="text/python" id="python-code">{{python_code}}</script>
    <script>{{js_code}}</script>
</body>
</html>

Template Variables

Use these placeholders that get replaced when generating agents:

  • {{agent_name}} - Agent's display name
  • {{description}} - Agent description
  • {{css_code}} - CSS styles from template
  • {{js_code}} - JavaScript from template
  • {{python_code}} - Python agent logic

CSS Styling

Style your template's interface:

body {
    font-family: system-ui, sans-serif;
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    background: #f5f5f5;
}

.container {
    background: white;
    border-radius: 12px;
    padding: 24px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

#chat-container {
    margin-top: 20px;
}

#messages {
    height: 400px;
    overflow-y: auto;
    border: 1px solid #e5e5e5;
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 16px;
}

#user-input {
    width: calc(100% - 100px);
    padding: 10px;
    border: 1px solid #e5e5e5;
    border-radius: 6px;
}

#send-btn {
    width: 80px;
    padding: 10px;
    background: #10b981;
    color: white;
    border: none;
    border-radius: 6px;
    cursor: pointer;
}

JavaScript Interactivity

Add client-side logic to wire up the UI. AgentOp injects a global initAgent() function that bootstraps Pyodide, loads packages, registers your Python tools, and starts the LLM. Your template JS typically handles UI events and delegates queries to the orchestrator:

// Initialize UI and wire up send button
document.addEventListener('DOMContentLoaded', function() {
    const input = document.getElementById('user-input');
    const sendBtn = document.getElementById('send-btn');
    const messages = document.getElementById('messages');

    sendBtn.addEventListener('click', sendMessage);
    input.addEventListener('keypress', function(e) {
        if (e.key === 'Enter') sendMessage();
    });

    async function sendMessage() {
        const userText = input.value.trim();
        if (!userText) return;

        appendMessage('user', userText);
        input.value = '';

        // process_user_query is the Python entry point injected by AgentOp.
        // It routes to the correct provider (OpenAI, Anthropic, or wllama)
        // and handles tool calling automatically.
        // Pass the input via pyodide.globals.set() to avoid string-escaping
        // issues with backslashes, newlines, or other special characters.
        try {
            const pyodide = window.pyodide;
            pyodide.globals.set('_user_input', userText);
            const result = await pyodide.runPythonAsync(
                'await process_user_query(_user_input)'
            );
            appendMessage('agent', result);
        } catch (err) {
            appendMessage('agent', 'Error: ' + err.message);
        }
    }

    function appendMessage(role, text) {
        const div = document.createElement('div');
        div.className = `message ${role}`;
        div.textContent = text;
        messages.appendChild(div);
        messages.scrollTop = messages.scrollHeight;
    }
});

πŸ’‘ For most templates, you don’t need custom JS

AgentOp's orchestrator (initAgent()) already wires up Pyodide, tool registration, and the LLM. The JavaScript above is a minimal example β€” the real data-analysis template, for instance, uses the orchestrator directly and only adds JS for file-upload handling and dashboard rendering.

Step 4: Configure Prompts

System Prompt

Define the agent's role and behavior:

You are a helpful assistant specializing in {{domain}}.
Your goal is to provide accurate and helpful information.

Guidelines:
- Be concise and clear
- Use tools when appropriate
- Ask clarifying questions if needed
- Stay within your domain of expertise

User Prompt Template

User: {input}

Context: {context}

Please provide a helpful response.

Prompt Variables

Define configurable variables in JSON format:

{
  "domain": {
    "type": "string",
    "default": "general assistance",
    "description": "The agent's area of expertise"
  },
  "tone": {
    "type": "string",
    "default": "professional",
    "options": ["professional", "casual", "formal"]
  }
}

Step 5: Add Default Python Code

Provide starter Python tool functions for agents using this template. AgentOp handles all LangChain / LangChain.js infrastructure automatically β€” template code only needs to define the async tool functions and export their schemas via get_tool_schemas():

import json

# Define async tool functions the agent can call.
# Use 'async def' β€” Pyodide runs these asynchronously.
# The docstring is used as the tool description sent to the LLM.
async def example_tool(query: str) -> str:
    """Process the user query and return a helpful result. Customize this for your use case."""
    # Replace with your real implementation (e.g. file parsing, API call, calculation)
    return f"Processed: {query}"

async def another_tool(input_text: str, max_results: int = 5) -> str:
    """Perform a secondary action with an optional result limit. Returns JSON-formatted output."""
    results = [f"item {i}" for i in range(max_results)]
    return json.dumps({"results": results})

def get_tool_schemas():
    """Return OpenAI-compatible function schemas for the JS\u2194Python bridge."""
    return [
        {
            "type": "function",
            "function": {
                "name": "example_tool",
                "description": "Process the user query and return a helpful result.",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {"type": "string", "description": "The query to process"}
                    },
                    "required": ["query"]
                }
            }
        },
        {
            "type": "function",
            "function": {
                "name": "another_tool",
                "description": "Perform a secondary action with an optional result limit.",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "input_text": {"type": "string", "description": "Text to process"},
                        "max_results": {"type": "integer", "description": "Max results to return (default 5)"}
                    },
                    "required": ["input_text"]
                }
            }
        }
    ]
# AgentOp injects the full LangChain orchestration around your code automatically.

💡 How tool functions work

You define async Python functions and a get_tool_schemas() function that describes them in OpenAI function-calling format. AgentOp's JavaScript↔Python bridge dispatches LLM tool calls to the correct Python function via Pyodide, then returns the result back to the LLM. No AgentExecutor or @tool decorator needed.

Step 6: Configure Packages

Specify default Python packages for agents built from this template:

{
  "pyodide_builtins": ["micropip"],
  "pypi_packages": {
    "python-dateutil": ">=2.8.0",
    "pyyaml": "*"
  }
}

πŸ’‘ LangChain is auto-injected

Do not add langchain, langchain_openai, or langchain_anthropic here. AgentOp injects the correct LangChain packages automatically based on the provider chosen at agent-creation time. Only list packages your Python tool functions actually import.

Step 7: Preview and Test

Use the preview feature to see how your template looks with sample data. The preview runs in a sandboxed iframe for safety.

Step 8: Publish

Save your template and set it to "Active" to make it available for agent creation.

Template Versioning

Creating Versions

Templates support prompt versioning to track changes over time:

  1. Edit a template's prompts
  2. Click "Save as New Version"
  3. Add a description of changes
  4. The version is saved with a sequential number

Managing Versions

  • View History: See all saved versions
  • Compare: Diff two versions side-by-side
  • Activate: Restore an older version
  • Description: Each version has a change log

πŸ’‘ Version Control Best Practices

Create a new version before making major prompt changes. This allows you to roll back if the changes don't work as expected.

Testing Templates (Eval Suite)

Every template can carry a test suite: a list of input β†’ assertion cases that check an agent's answers. The suite belongs to the template, so every agent built from it can be tested against the same cases β€” before and after you change prompts or code.

Defining Test Cases

Open the run page of any agent built from your template. As the template's creator you'll see a Test suite panel below the agent. Each case has:

  • Input: the message sent to the agent
  • Assertion: how the output is checked β€” contains / does not contain / equals / matches a regular expression / is JSON with a key
  • Expected value: the text, pattern, or key the assertion looks for

Running the Suite

  1. Launch the agent on its run page (any provider β€” local or cloud)
  2. Wait until it's ready (model loaded, or API key entered)
  3. Click Run all tests β€” each input is sent to the live agent in your browser, one case at a time
  4. Outputs are scored server-side and the verdicts appear per case, with an explanation for every failure

Runs are saved per template, so you can compare pass rates across providers and across prompt versions. As with everything on AgentOp, the AI inference happens in your browser β€” the server only scores the returned text.

πŸ’‘ Eval Best Practices

Prefer robust assertions ("contains" a key fact, "matches" a format regex) over exact "equals" β€” small local models word answers differently between runs. Re-run the suite after every prompt change and before publishing a new version.

Using Templates

When Creating Agents

When creating a new agent, you select a template which provides:

  • Initial HTML structure and styling
  • Default Python code to customize
  • Prompt configurations
  • Recommended packages

Customizing from Templates

After selecting a template, you can customize everything:

  • Modify the Python code
  • Adjust prompts and variables
  • Add or remove packages
  • Change metadata

Template Independence

Agents created from a template are independent. Changes to the template don't affect existing agents (only new agents created from it).

Best Practices

Template Design

  • Keep HTML structure simple and semantic
  • Use CSS variables for easy theming
  • Make layouts responsive for mobile devices
  • Include accessibility features (ARIA labels, keyboard navigation)

Code Quality

  • Provide well-commented default Python code
  • Include error handling examples
  • Use clear tool names and descriptions
  • Keep default implementations simple but functional

Prompts

  • Make system prompts clear and specific
  • Use variables for customizable parts
  • Provide helpful few-shot examples
  • Document variable options and defaults

Documentation

  • Write clear template descriptions
  • Explain what variables do
  • List required vs. optional packages
  • Include usage examples in the description

Sharing Templates

Public vs. System Templates

  • Public Templates: Created by users, visible to all
  • System Templates: Curated by AgentOp team, cannot be deleted

Template Marketplace

Popular templates appear in the template marketplace, sorted by:

  • Usage count (agents created from template)
  • Recently updated
  • Category
  • Creator

Next Steps