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:
- Edit a template's prompts
- Click "Save as New Version"
- Add a description of changes
- 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
- Launch the agent on its run page (any provider β local or cloud)
- Wait until it's ready (model loaded, or API key entered)
- Click Run all tests β each input is sent to the live agent in your browser, one case at a time
- 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