Patterns
Patterns
A caddisfly larva builds its protective case by selecting and binding together whatever materials suit its environment — grains of sand, bits of shell, fragments of leaf. OpenCaddis agents work the same way: you compose them from plugins, tools, and system prompts to fit the task at hand.
These patterns are proven agent compositions you can tie together today. Each one walks through the config, the conversation, and what's happening under the hood.
The Hatch: Agent Manager that Spawns a Personal Secretary
In nature, a caddisfly hatch is an explosive event — hundreds of new flies emerging at once. This pattern captures that energy: a single Agent Manager that hatches purpose-built agents on demand through natural conversation. Instead of pre-configuring every agent you might need in opencaddis.json, you set up one agent and let it spin up the rest.
Configure one agent with the AgentManagement plugin. Then ask it in plain English to create whatever specialized agent you need. The new agent appears in your sidebar instantly — its own conversation thread, system prompt, and plugin set, ready to go.
Step 1: Configure the Agent Manager
Add this to your opencaddis.json agents array:
{
"Handle": "Agent Manager",
"AgentType": "assistant",
"Models": ["default"],
"SystemPrompt": "You are an agent factory. When the user describes a role or task, create a well-configured agent for it using CreateAgent. Choose appropriate plugins and tools for the agent's purpose. Always confirm what you created and suggest how the user can start using the new agent.",
"Plugins": ["AgentManagement"]
}
That's it — one agent in your config. The AgentManagement plugin gives it two tools: CreateAgent (to spawn new agents) and GetAgentHealth (to check on running agents).
Step 2: Ask for a Secretary
Open the Agent Manager chat and type something like:
Create a personal secretary agent called "Secretary" that does dictation — I want to
be able to tell it things to remember and it stores them for me. It should also be
able to set reminders so I don't forget follow-ups. Give it the ability to check the
current date and time so it can set reminders accurately.
The Agent Manager interprets your request and calls CreateAgent with the right configuration. Behind the scenes, the tool call looks like this:
{
"handle": "Secretary",
"agentType": "assistant",
"systemPrompt": "You are a personal secretary and dictation assistant. Your primary job is to listen to what the user tells you and commit it to memory so they can retrieve it later. Organize information clearly — use labels like 'meeting notes', 'ideas', 'to-do' as memory sources so things are easy to find. When the user mentions a deadline or follow-up, proactively offer to set a reminder. Always check the current date and time before scheduling reminders so you set them accurately. When the user asks you to recall something, search memory and present what you find in a clear, organized way.",
"plugins": ["Memory", "Reminders"],
"tools": ["GetDateTime"]
}
Notice that Memory and Reminders are plugins (which bring along all their tools), while GetDateTime is a standalone tool available to any agent. The tools array lets you cherry-pick individual capabilities without enabling an entire plugin.
Step 3: Use Your New Secretary
The Secretary agent appears in your sidebar immediately. Switch to it and start dictating. Here's what a real conversation looks like:
Just got off a call with the Contoso team. They want the API proposal by Friday. Sarah is handling the auth section, I need to write the rate limiting section. They also mentioned they're switching from REST to gRPC for the streaming endpoints — make sure I remember that.
Got it. I've saved the following to memory:
- Meeting notes (Contoso) — API proposal due Friday. Sarah owns auth section, you own rate limiting section. Contoso switching from REST to gRPC for streaming endpoints.
Would you like me to set a reminder for Thursday to give you a heads-up on the Friday deadline?
Yes, remind me Thursday morning at 9 AM. Also set one for Wednesday at 2 PM to start drafting.
Done. I checked the current time and set two reminders:
- Wednesday 2:00 PM — "Start drafting the rate limiting section for the Contoso API proposal (due Friday)"
- Thursday 9:00 AM — "Contoso API proposal due tomorrow. Check in with Sarah on auth section."
Days later, you come back and ask:
What did Contoso say about their API architecture?
From your meeting notes: Contoso is switching from REST to gRPC for their streaming endpoints. The API proposal covering this is due Friday, with Sarah handling the auth section and you writing the rate limiting section.
Under the Hood
| When you say... | The Secretary calls... | What happens |
|---|---|---|
| "Remember that Contoso is switching to gRPC" | MemorySave |
Content is chunked, embedded into a 1536-dim vector, and stored in the local SQLite database with a source label |
| "Remind me Thursday at 9 AM" | GetDateTime → RegisterReminder |
Checks the current date/time to calculate the correct trigger, then registers a one-shot reminder |
| "What did Contoso say about their architecture?" | MemorySearch |
Query is embedded and compared against stored vectors via cosine similarity — finds the meeting notes |
| "Remind me every Monday at 9 AM to review notes" | GetDateTime → RegisterReminder (recurring) |
Sets a recurring reminder that fires weekly |
Why This Pattern Works
- You don't need to plan ahead. The Agent Manager creates agents on demand — no restarting, no editing config files. Need a code reviewer? A recipe organizer? A meeting note-taker? Just ask.
- Each agent is isolated. The Secretary has its own conversation, its own memory labels, and only the tools it needs. It can't run PowerShell or browse the web — it's scoped to exactly what a secretary does.
- Memory persists across sessions. Everything the Secretary stores lives in the vector database. Close OpenCaddis, come back a week later, and your notes are still there — searchable by meaning, not just keywords.
- Reminders are proactive. Once set, reminders fire as system messages in the Secretary's chat. You'll see them the next time you open that conversation, even if you forgot to check.
The Nymph: Orchestrated Research with Persistent Memory
The caddisfly nymph spends most of its life underwater, quietly building and gathering. This pattern does the same: a Workflow agent that plans a research project, delegates tasks to a specialist researcher agent, and verifies the results — coordinating multi-step research from a single prompt.
This pattern uses two agents: a Workflow orchestrator that plans and coordinates, and a Research assistant that does the actual web browsing, memory saving, and report writing.
{
"Agents": [
{
"Handle": "Researcher",
"AgentType": "assistant",
"Models": ["default"],
"SystemPrompt": "You are a thorough research analyst. Search the web using WebBrowser, save key findings to Memory with descriptive source labels, and compile structured reports to the file system. Always cite your sources.",
"Plugins": ["WebBrowser", "Memory", "FileSystem"],
"Args": {
"FileSystem:RootPath": "C:\\Research",
"Memory:MaxResults": 10
}
},
{
"Handle": "Research Lead",
"AgentType": "workflow",
"Models": ["default"],
"SystemPrompt": "You are a research coordinator. Break complex research questions into focused tasks, delegate them to the Researcher agent, and verify the results meet quality standards before marking them complete.",
"Args": {
"ManagedAgents": "Researcher"
}
}
]
}
What the Workflow Agent Does
Ask the Research Lead something like "Research the current state of WebAssembly for server-side applications and write a report" and the Workflow pipeline activates:
- Planning — The Workflow agent creates a structured plan with tasks like: define scope, gather data on WASI, compare frameworks, assess production readiness, compile report
- Approval — The plan is presented to you. Say
"go"to start, or provide feedback to adjust - Execution — Each task is delegated to the Researcher agent, which:
- Uses
NavigateAndReadto visit documentation, blog posts, and GitHub repos - Calls
MemorySaveafter each source with labels like"wasm-server-research" - Writes the final report to the file system via
WriteFile
- Uses
- Acceptance — After each task, the Workflow agent evaluates the result against acceptance criteria. If a task falls short, it retries with improved instructions
- Completion — The Workflow agent summarizes what was accomplished across all tasks
The result: a structured report in C:\Research, plus everything indexed in memory. Weeks later you can ask the Researcher directly: "What did I find out about WASI compatibility?" and get answers without re-doing the research.
A single Assistant agent could browse and save too, but it would just execute tool calls sequentially with no overall plan. The Workflow agent plans the research, delegates focused tasks, and verifies each result meets acceptance criteria before moving on. For open-ended research where you don't know what you'll find, that structured approach catches gaps a simple agent would miss.
The Dry Fly: Daily Email Briefing on a Schedule
A dry fly sits on the surface, waiting for the right moment. This agent does the same — it waits for a scheduled reminder to trigger, then skims your inbox and delivers a summary. Recurring reminders combined with memory mean it builds a running log of your daily briefings that you can query at any time.
{
"Handle": "Morning Briefing",
"AgentType": "assistant",
"Models": ["default"],
"SystemPrompt": "You are a daily briefing assistant. When triggered or asked, read the user's unread emails, categorize them by urgency (action required, FYI, low priority), summarize each one in 1-2 sentences, and save the daily summary to memory with today's date as the source label. Flag anything that has a deadline within 48 hours.",
"Plugins": ["Microsoft365Email", "Memory", "Reminders"],
"Tools": ["GetDateTime"],
"Args": {
"Microsoft365Email:MaxResults": 50
}
}
The Workflow
- On first use, tell the agent: "Set a recurring reminder every weekday at 8:30 AM to run my morning briefing."
- Each morning, the reminder fires as a system message in the chat
- The agent calls
ListEmailswithunreadOnly: true, reads the important ones withReadEmail - It categorizes and summarizes everything, then saves the digest via
MemorySavewith a source like"briefing-2026-02-17" - At the end of the week, ask: "Summarize what happened this week based on my daily briefings" — it searches memory across all the daily sources and gives you a weekly rollup
This pattern requires the Microsoft 365 email integration to be configured with the OAuth device code flow.
The Streamer: Web Capture + File System in Tandem
A streamer fly is designed to cover water — it moves through the current, grabs attention, and brings something back. This pattern pairs the WebBrowser and FileSystem plugins so an agent can reach out to the web, capture what it finds, and land it exactly where you need it on your machine.
WebBrowser handles navigation and screenshots. FileSystem handles file operations. Together they let an agent grab content from any public URL — a radar image, a dashboard, a chart — and save it to a specific path on your local machine. One prompt, two plugins, zero manual steps.
The Config
{
"Handle": "Web Capture",
"AgentType": "assistant",
"Models": ["default"],
"SystemPrompt": "You are a web capture assistant. You browse websites, take screenshots, extract content, and save files to the local file system. When asked to capture or screenshot a page, navigate to it, take a full-page screenshot, then copy or move the screenshot to the user's requested location. Confirm the file path when done.",
"Plugins": ["WebBrowser", "FileSystem"],
"Args": {
"WebBrowser:ScreenshotPath": "C:\\temp\\screenshots",
"WebBrowser:Headless": true,
"FileSystem:RootPath": "C:\\temp"
}
}
WebBrowser:ScreenshotPath tells the browser plugin where to save screenshots. FileSystem:RootPath tells the file system plugin where it can operate. Set RootPath to a parent directory that includes both the screenshot directory and any target locations, so the agent can move files between them.
Example: Grab the Weather Radar
Open the Web Capture agent and ask:
Take a screenshot of https://radar.weather.gov/ and save it to C:\temp\radar.png
Done. Here's what I did:
- Navigated to
https://radar.weather.gov/ - Took a full-page screenshot (saved to
C:\temp\screenshots\screenshot-2026-02-17-084532.png) - Moved the file to
C:\temp\radar.png
The weather radar screenshot is now at C:\temp\radar.png.
Under the Hood
| Step | Tool Called | Plugin | What Happens |
|---|---|---|---|
| 1 | NavigateAndRead |
WebBrowser | Playwright opens Chromium, navigates to the radar URL, waits for the page to load |
| 2 | TakeScreenshot |
WebBrowser | Captures a full-page screenshot, saves it to the ScreenshotPath directory with a timestamped filename |
| 3 | MoveFile |
FileSystem | Moves the screenshot from C:\temp\screenshots\*.png to C:\temp\radar.png |
More Ideas for This Pattern
Once you have web capture + file system working together, the possibilities open up:
Go to our company status page at https://status.example.com, screenshot it, and save it to C:\temp\status-report.png. Then extract the page text and save that to C:\temp\status-report.txt
All done:
- Screenshot saved to
C:\temp\status-report.png - Page text saved to
C:\temp\status-report.txt(12 services, all operational)
Read the pricing table from https://azure.microsoft.com/en-us/pricing/details/cosmos-db/ and save it as a CSV to C:\temp\cosmos-pricing.csv
Extracted the pricing table and saved it as CSV to C:\temp\cosmos-pricing.csv (15 rows covering provisioned throughput, serverless, and autoscale tiers).
Why This Pattern Works
- Two plugins, one workflow. WebBrowser reaches out to the web. FileSystem puts the result exactly where you want it. The agent coordinates them naturally — no scripts, no manual steps.
- Screenshots + text extraction.
TakeScreenshotcaptures the visual,NavigateAndRead/ExtractContentcaptures the data. Use both when you need a visual record and the raw content. - Any URL, any destination. The same pattern works for dashboards, documentation, pricing pages, social feeds, news — anything publicly accessible. The FileSystem plugin can write to any path within its
RootPath. - Runs from Visual Studio / .NET CLI. This pattern needs host file access, so it works best when running OpenCaddis locally (not in Docker, where FileSystem is sandboxed to the container).
Both the WebBrowser ScreenshotPath and the FileSystem RootPath reference host directories. When running in Docker, these paths resolve inside the container — screenshots won't land on your desktop. Run from Visual Studio or .NET CLI for full host access.
Tie Your Own
Every fly angler has their go-to patterns, but the best ones are the ones you tie yourself. Here are some principles for composing your own agent patterns:
- Start with one Agent Manager. You can bootstrap an entire workspace from a single agent with the AgentManagement plugin — no need to pre-configure everything in
opencaddis.json. - Use the
Toolsarray for precision. Standalone tools likeGetDateTimecan be added to any agent without needing a full plugin. Keep agents focused by giving them only what they need. - Label your memory sources. Consistent source labels (
"meeting-notes","project-alpha","briefing-2026-02-17") make it easy to search and filter later. - Match agent type to task complexity. Use Assistant for quick, direct tasks. Use Delegate when you want a single entry point that intelligently routes requests to the right specialist. Use Workflow when you need to coordinate multiple agents across multi-step projects. Use Event Log for application diagnostics. Don't use a Workflow agent for simple single-agent tasks — the planning and approval overhead isn't worth it. If users just need to chat naturally without choosing an agent, a Delegate in front of your specialists is the sweet spot.
- Combine recurring reminders with memory. Reminders trigger the agent, memory gives it context from previous runs. Together they create agents that operate on a schedule with continuity across sessions.
- Scope plugins tightly. A secretary doesn't need PowerShell. A code reviewer doesn't need email. The tighter you scope an agent's capabilities, the more focused and reliable its behavior.