✍️ Blog Post

Building an OpenClaw Research Assistant Skill

10 min read

A research assistant skill turns OpenClaw into your personal analyst. It gathers source material, synthesizes findings, and builds a structured knowledge base you can query later. This guide walks through building one from scratch.

What a Research Assistant Skill Does

Most research workflows follow a repeating cycle: identify a topic, search for sources, read and extract key points, organize findings, and compile a summary. A research assistant skill automates the parts of that cycle that do not require judgment — searching, fetching, extracting, and organizing — so you can focus on analysis and decision-making.

The skill we are building in this guide accepts a research topic, searches multiple sources, extracts structured information, and returns a formatted research brief. It can be run on demand or scheduled via a cron hook for recurring research tasks.

Prerequisites

  • OpenClaw running — any deployment (Mac Mini, VPS, Raspberry Pi)
  • Web fetch capability — the web_fetch tool or an MCP server for browsing
  • Basic familiarity with OpenClaw skill structure

If you are new to skills entirely, start with the skills guide first. This article assumes you know how skills are structured and focuses on the research assistant pattern.

Step 1: Define the Skill Directory and Configuration

Every OpenClaw skill lives in its own directory within the skills folder. Create the directory for your research assistant skill:

mkdir -p ~/.openclaw/skills/research-assistant

Create a configuration file at ~/.openclaw/skills/research-assistant/config.json:

{
  "sources": {
    "web_search": {
      "enabled": true,
      "max_results": 8
    },
    "web_fetch": {
      "enabled": true,
      "max_pages": 5,
      "max_chars_per_page": 8000
    }
  },
  "output": {
    "format": "markdown",
    "include_sources": true,
    "include_summary": true
  },
  "default_topic": "latest developments in agentic AI"
}

This configuration defines which source types the skill uses, how many results to fetch per source, and how to format the output. Keeping these settings in a config file means you can change behavior without editing the skill logic.

Step 2: Write the Skill Script

Create ~/.openclaw/skills/research-assistant/skill.py:

#!/usr/bin/env python3
"""Research Assistant Skill - Automated market and topic research."""

import json, sys, os, subprocess
from datetime import datetime

CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.json")

def load_config():
    with open(CONFIG_PATH) as f:
        return json.load(f)

def web_search(query, max_results=8):
    result = subprocess.run(
        ["openclaw", "web_search", "--query", query, "--count", str(max_results)],
        capture_output=True, text=True, timeout=30
    )
    if result.returncode != 0:
        return {"error": result.stderr, "results": []}
    return json.loads(result.stdout)

def fetch_page(url, max_chars=8000):
    result = subprocess.run(
        ["openclaw", "web_fetch", "--url", url, "--max-chars", str(max_chars)],
        capture_output=True, text=True, timeout=30
    )
    if result.returncode != 0:
        return {"error": result.stderr, "content": ""}
    return {"content": result.stdout[:max_chars]}

def synthesize_brief(topic, search_results, page_contents):
    lines = []
    lines.append(f"# Research Brief: {topic}")
    lines.append(f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M')}")
    lines.append(f"**Sources consulted:** {len(search_results)}")
    lines.append("")
    lines.append("## Summary")
    lines.append(f"This brief covers recent information about **{topic}**.")
    lines.append("")
    lines.append("## Key Findings")
    for i, result in enumerate(search_results[:5]):
        lines.append(f"### {i+1}. {result.get('title', 'Untitled')}")
        lines.append(f"**Source:** {result.get('url', 'No URL')}")
        desc = result.get('description', '')
        if desc:
            lines.append(f"_{desc}_")
        if i < len(page_contents) and page_contents[i].get("content"):
            lines.append(f"\n> {page_contents[i]['content'][:500]}")
        lines.append("")
    lines.append("## Source URLs")
    for result in search_results:
        lines.append(f"- [{result.get('title', 'Untitled')}]({result.get('url', '#')})")
    lines.append("")
    lines.append("---")
    lines.append("*Generated by OpenClaw Research Assistant Skill*")
    return "\n".join(lines)

def run_research(topic=None):
    config = load_config()
    topic = topic or config.get("default_topic", "latest developments")
    print(f"Running research on: {topic}")
    print("-" * 60)
    search_config = config["sources"]["web_search"]
    search_results = web_search(topic, search_config["max_results"])
    if "error" in search_results:
        print(f"Search error: {search_results['error']}")
        return
    fetch_config = config["sources"]["web_fetch"]
    page_contents = []
    urls = [r.get("url") for r in search_results.get("results", []) if r.get("url")]
    for url in urls[:fetch_config["max_pages"]]:
        content = fetch_page(url, fetch_config["max_chars_per_page"])
        page_contents.append(content)
    brief = synthesize_brief(topic, search_results.get("results", []), page_contents)
    print("\n" + brief)

if __name__ == "__main__":
    topic = sys.argv[1] if len(sys.argv) > 1 else None
    run_research(topic)

Step 3: Register the Skill in OpenClaw

Add the skill to your OpenClaw configuration. Open ~/.openclaw/openclaw.json and add an entry under the skills section:

{
  "skills": {
    "entries": {
      "research-assistant": {
        "path": "/Users/yourname/.openclaw/skills/research-assistant/skill.py",
        "description": "Automated research assistant that searches, fetches, and synthesizes findings into structured briefs",
        "timeout": 120,
        "type": "script"
      }
    }
  }
}

After adding this entry, restart OpenClaw to pick up the new skill:

openclaw gateway restart

Verify the skill is loaded:

openclaw skills list

You should see research-assistant in the list.

Step 4: Run a Research Session

Invoke the skill from any OpenClaw session:

openclaw skill run research-assistant -- "AI agent benchmarks 2026"

Or, from within an OpenClaw chat session, simply say:

Run the research assistant skill on AI agent benchmarks 2026

OpenClaw routes this to the skill and returns a formatted research brief. The first run will take 30 to 90 seconds depending on how many sources are consulted. The output is a markdown brief with a summary, key findings, and source URLs.

Step 5: Add Knowledge Base Persistence

A research assistant becomes more valuable when it remembers past work. Add a storage layer that saves briefs to a local knowledge base:

import json, os
from datetime import datetime

KNOWLEDGE_DIR = os.path.expanduser("~/.openclaw/skills/research-assistant/knowledge")

def save_to_knowledge_base(topic, brief):
    os.makedirs(KNOWLEDGE_DIR, exist_ok=True)
    slug = topic.lower().replace(" ", "-")[:50]
    filename = f"{datetime.now().strftime('%Y%m%d')}-{slug}.md"
    path = os.path.join(KNOWLEDGE_DIR, filename)
    with open(path, "w") as f:
        f.write(brief)
    print(f"Brief saved to: {path}")

def list_knowledge():
    os.makedirs(KNOWLEDGE_DIR, exist_ok=True)
    files = sorted(os.listdir(KNOWLEDGE_DIR), reverse=True)
    print("\nSaved research briefs:")
    for f in files[:10]:
        print(f"  - {f}")

Now every research session saves a permanent record. You can browse past briefs with openclaw skill run research-assistant -- list.

Step 6: Schedule Recurring Research

Many research topics benefit from regular updates — competitor monitoring, industry news, or technology tracking. Add a cron hook to run the skill on a schedule:

{
  "hooks": {
    "entries": {
      "weekly-competitor-research": {
        "cron": "0 9 * * 1",
        "action": "skill",
        "params": {
          "name": "research-assistant",
          "args": [
            "competitor landscape AI coding tools 2026"
          ]
        },
        "description": "Weekly competitive intelligence brief"
      },
      "daily-industry-news": {
        "cron": "0 7 * * 1-5",
        "action": "skill",
        "params": {
          "name": "research-assistant",
          "args": [
            "latest AI industry news this week"
          ]
        },
        "description": "Daily industry news roundup"
      }
    }
  }
}

These hooks run the research skill automatically. The weekly competitor brief runs Monday at 9 AM, and the daily news roundup runs every weekday at 7 AM. Each run saves a new brief to the knowledge base.

For more complex hook setups — chaining multiple skills or conditional execution — read the hooks patterns guide.

Step 7: Make Results Available to Other Agents

A research assistant that only outputs to a terminal is useful but limited. The real power comes when other agents in your fleet can query the knowledge base. To enable this, store the knowledge base in a location your agents can read, and add a simple query interface:

def query_knowledge_base(search_term):
    """Search saved briefs for a term and return matching excerpts."""
    results = []
    for filename in sorted(os.listdir(KNOWLEDGE_DIR), reverse=True):
        if not filename.endswith(".md"):
            continue
        path = os.path.join(KNOWLEDGE_DIR, filename)
        with open(path) as f:
            content = f.read()
        if search_term.lower() in content.lower():
            results.append({"file": filename, "preview": content[:300]})
    return results

Now any agent can call openclaw skill run research-assistant -- query "agent benchmarks" to find past research on a topic. This turns the skill from a one-shot research tool into a shared intelligence layer for your entire agent fleet.

Troubleshooting

Skill not found after restart. Check that the path in your OpenClaw config is absolute. OpenClaw does not expand ~ in all config parsers — use the full path like /Users/yourname/.openclaw/skills/research-assistant/skill.py.

Timeout on search or fetch. Increase the timeout value in your skill registration config from 120 to 300 seconds if your sources are slow. Alternatively, reduce max_pages in the config.

JSON parsing errors. The skill assumes openclaw web_search --json returns valid JSON. Verify the output format for your OpenClaw version by running the command directly.

Knowledge base too large. Add a retention policy — delete briefs older than 90 days unless archived. Add a max_age_days config parameter and clean up on each run.

Next Steps

This skill handles the research pipeline: search, fetch, synthesize, store. Once it is running, consider connecting it to other parts of your agent fleet:

The pattern described here — search, fetch, synthesize, store — works for any domain. Replace the research topic with market analysis, technical documentation, regulatory updates, or customer feedback collection, and the same skill structure applies.