# Local Deep Research Skill

> Local Deep Research Skill

- Skill: `eplt/local-deep-research-skill` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add eplt/local-deep-research-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/eplt/local-deep-research-skill/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- Author: eplt (https://skillmd.com/u/eplt)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/eplt/local-deep-research-skill

---


# Local Deep Research Skill

This skill interfaces with a locally-hosted LDR (Local Deep Research) service to perform multi-cycle, iterative research with full citations and source tracking.

## What to consider before installing

- **LDR service**: The script talks only to the URL in `LDR_BASE_URL` (default `http://127.0.0.1:5000`). Only point it at an LDR instance you control. Do not set it to an unknown or untrusted remote host.
- **Required binaries**: Ensure `curl` and `jq` are installed on the host where the skill runs.
- **Credentials**: If your LDR instance requires login, set `LDR_SERVICE_USER` and `LDR_SERVICE_PASSWORD` (or `LDR_USERNAME`/`LDR_PASSWORD`) via environment variables or a local `.env` file only. Use a dedicated, low-privilege LDR account (e.g. `openclaw_service`). Do not store secrets in committed config or in the skill directory.
- **Sourced .env**: The script optionally sources `~/.config/local_deep_research/config/.env` if that file exists. That file may expose any variables it contains to the script. Verify the contents of that path before use; do not place unrelated secrets there.
- **Review the script**: The script performs form-based session+CSRF login and uses an ephemeral cookie jar. It does not send data to any endpoint other than the configured LDR service. You can review `scripts/ldr-research.sh` before use. For higher assurance, run it in an isolated environment (e.g. container or VM) with network restricted to your LDR host.

## Configuration

### Credentials (local-only, never transmitted)

LDR uses **session-cookie auth with CSRF protection** (not HTTP Basic Auth). The skill script performs a proper login flow: GET login page → obtain session cookie and CSRF token → POST credentials + CSRF → reuse session cookie (and CSRF for POSTs) for all API calls. Username and password are used **only** to create a session with your **local** LDR instance; they are never sent to ClawHub, GitHub, or any other server.

**Do not** put credentials in skill config or committed files. Use **environment variables or a local `.env` file** only (e.g. `LDR_SERVICE_USER`, `LDR_SERVICE_PASSWORD`, or `LDR_USERNAME`/`LDR_PASSWORD`). Optional: LDR’s `~/.config/local_deep_research/config/.env` is sourced by the script if present. Use a dedicated LDR user (e.g. `openclaw_service`) for this skill.

### All configuration options

- `LDR_BASE_URL` — LDR service URL (default: `http://127.0.0.1:5000`)
- `LDR_LOGIN_URL` — Login page URL for session + CSRF (default: `$LDR_BASE_URL/auth/login`)
- `LDR_SERVICE_USER` or `LDR_USERNAME` — LDR account username (local auth only)
- `LDR_SERVICE_PASSWORD` or `LDR_PASSWORD` — LDR account password (local auth only)
- `LDR_DEFAULT_MODE` — Default research mode: `quick` (Quick Summary) or `detailed` (Detailed Report) (default: `detailed`)
- `LDR_DEFAULT_LANGUAGE` — Default output language code for report/summary (e.g. `en`, `es`, `fr`, `de`, `zh`, `ja`); empty = LDR default
- `LDR_DEFAULT_SEARCH_TOOL` — Default search tool: `searxng`, `auto`, `local_all` (default: `auto`)

## Research modes (Quick Summary vs Detailed Report)

- **`quick`** — **Quick Summary**: fewer cycles, shorter output, faster. Use when the user wants a concise summary or a quick overview.
- **`detailed`** — **Detailed Report**: full multi-cycle research, full markdown report, full citations and sources. Use when the user wants comprehensive analysis, literature review, or in-depth coverage.

## Actions

### start_research

Fire-and-forget: submit a query to LDR and return a research ID immediately.

**Inputs:**
- `query` (required) — The research question or topic
- `mode` (optional) — `quick` (Quick Summary) or `detailed` (Detailed Report) (default from config)
- `language` (optional) — Output language for the report/summary, e.g. `en`, `es`, `fr`, `de`, `zh`, `ja` (default from config or LDR default)
- `search_tool` (optional) — `searxng`, `auto`, `local_all` (default from config)
- `iterations` (optional) — Number of research cycles (default: LDR's default)
- `questions_per_iteration` (optional) — Questions to generate per cycle

**Returns:**
```json
{
  "research_id": "uuid-string",
  "mode": "detailed",
  "search_tool": "auto",
  "submitted_at": "2026-03-10T08:00:00Z",
  "status": "queued"
}
```

**Usage:**
```bash
# Quick Summary (faster, shorter)
scripts/ldr-research.sh start_research --query "Solid-state battery advances" --mode quick

# Detailed Report with output in Spanish
scripts/ldr-research.sh start_research \
  --query "What are the latest developments in solid-state batteries?" \
  --mode detailed \
  --language es \
  --search_tool searxng
```

### get_status

Check the status of a research job.

**Inputs:**
- `research_id` (required) — The research job ID from start_research

**Returns:**
```json
{
  "research_id": "uuid-string",
  "state": "pending|running|completed|failed|timeout",
  "progress": 45,
  "message": "Synthesizing sources from iteration 2...",
  "last_milestone": "Generated 12 questions from 8 sources"
}
```

**Usage:**
```bash
scripts/ldr-research.sh get_status --research_id <uuid>
```

### get_result

Fetch the complete research report once finished.

**Inputs:**
- `research_id` (required) — The research job ID

**Returns:**
```json
{
  "research_id": "uuid-string",
  "query": "original query",
  "mode": "detailed",
  "summary": "executive summary text",
  "report_markdown": "full markdown report",
  "sources": [
    {
      "id": 1,
      "title": "Source Title",
      "url": "https://example.com",
      "snippet": "relevant excerpt",
      "type": "web|local_doc"
    }
  ],
  "iterations": 3,
  "created_at": "2026-03-10T08:00:00Z",
  "completed_at": "2026-03-10T08:15:00Z"
}
```

**Usage:**
```bash
scripts/ldr-research.sh get_result --research_id <uuid>
```

## Orchestration Pattern

### One-shot (wait for completion)

For interactive sessions where the user can wait:

1. Call `start_research`
2. Poll `get_status` every 10-30 seconds
3. When `state == "completed"`, call `get_result`
4. Present the report to the user

### Async (fire-and-forget with follow-up)

For background processing:

1. Call `start_research`, return the `research_id` to the user
2. User can check status later with `get_status --research_id <id>`
3. When ready, call `get_result` to fetch the complete report

### Chained workflows

After research completes:

1. Call `get_result` to get sources
2. Pass sources to other skills (e.g., `markdown-converter`, `summarize`)
3. Build RAG indexes or knowledge bases from the sources

## Error Handling

### start_research failures

- **HTTP/network errors** — Retry with exponential backoff (3 attempts)
- **LDR validation errors** — Return error to user (bad query, invalid params)
- **Auth failures** — Check credentials, return clear error

### get_status / get_result failures

- **Temporarily unavailable** — Retry 2-3 times before surfacing error
- **Research not found** — Return "unknown research_id" error
- **Timeout** — Return state with timeout reason

## Timeouts

- **Per HTTP request** — 30-60 seconds (configurable)
- **Total research duration** — No client-side limit (LDR manages this)
- **Status polling interval** — 10-30 seconds recommended

## Example Session

```
User: "Research the latest developments in quantum computing"

Assistant: Starting deep research with LDR...
→ start_research(query="latest developments in quantum computing", mode="detailed")
→ Returns: research_id="abc-123", status="queued"

Assistant: Research started (ID: abc-123). This will take ~5-10 minutes.
I'll check the progress and let you know when it's complete.

[After polling...]

Assistant: Research complete! Here's what I found:

## Summary
[summary from get_result]

## Full Report
[report_markdown from get_result]

## Sources (12 found)
1. [Source 1 title](url)
2. [Source 2 title](url)
...
```

## Related Skills

- **academic-deep-research** — Alternative for academic-focused research with APA 7th citations
- **deep-research-pro** — Web-based deep research (no local LDR required)
- **tavily** / **searxng** — Simple web search for quick lookups
- **summarize** — Process LDR output for additional summarization

## Troubleshooting

### LDR service not responding

1. Check `LDR_BASE_URL` is correct
2. Verify LDR service is running: `curl http://127.0.0.1:5000/health`
3. Check LDR logs for errors

### Authentication failures

1. Ensure credentials are set via **env or local .env only** (e.g. `LDR_SERVICE_USER`, `LDR_SERVICE_PASSWORD`), not in committed config.
2. LDR uses **session + CSRF** (not Basic Auth). The script GETs the login page, extracts the CSRF token, then POSTs the login form. If LDR uses a different login path or field names, set `LDR_LOGIN_URL` or see the script’s login section.
3. Test: run the script with credentials set and check for "Login successful"; or open `LDR_LOGIN_URL` in a browser and sign in there to verify LDR is up.

### Research stuck in "running" state

1. Check LDR service health
2. Review LDR logs for stuck jobs
3. Consider timeout and restart if >30 minutes with no progress

