ragora

Search & Research
v1.0.1
Benign

Use Ragora MCP tools and REST API to discover, search, and synthesize answers from knowledge bases.

2751 downloads751 installsby @mregmi

Setup & Installation

Install command

clawhub install mregmi/ragora

If the CLI is not installed:

Install command

npx clawhub@latest install mregmi/ragora

Or install with OpenClaw CLI:

Install command

openclaw skills install mregmi/ragora

or paste the repo link into your assistant's chat

Install command

https://github.com/openclaw/skills/tree/main/skills/mregmi/ragora

What This Skill Does

Ragora is a knowledge base platform that indexes documents into searchable collections. This skill queries those collections via MCP tools or a REST API, returning chunk-level results with source citations. It supports cross-collection comparison, versioned document lookup, tag-based filtering, and credit balance checks.

Returns answers grounded in private knowledge bases with exact source citations, rather than relying on model training data or general web search.

When to Use It

  • Finding internal HR or remote work policies across company handbooks
  • Comparing SLA terms and penalty clauses between two vendor contracts
  • Researching a company's security certifications and past audit history
  • Looking up what changed between two versions of an API's authentication flow
  • Verifying a compliance claim against SOC 2 documentation
View original SKILL.md file
# Ragora Skill for OpenClaw

Use this skill to answer questions with Ragora data. You have two integration paths:

1. **MCP (Model Context Protocol)** — preferred when your client supports MCP tool binding.
2. **REST API** — use directly via HTTP when MCP is unavailable or when you need fine-grained control.

Both paths share the same authentication, data model, and search capabilities.

## Source of Truth Docs

Consult these docs first when behavior differs across environments:

- MCP guide: `https://ragora.app/docs?section=mcp-guide`
- Getting started: `https://ragora.app/docs?section=getting-started`
- API overview: `https://ragora.app/docs?section=api-overview`
- Retrieve API: `https://ragora.app/docs?section=api-retrieve`
- Errors and limits: `https://ragora.app/docs?section=api-errors`
- Billing API: `https://ragora.app/docs?section=api-billing`

---

## Core Concepts

Before using any tools, understand the Ragora data model.

### Collections

A **collection** is a knowledge base — a curated set of documents indexed for semantic search. Each collection has:

- **Name** — human-readable label (e.g., "Employee Handbook").
- **Slug** — URL-safe identifier used in dynamic tools and API paths (e.g., `employee_handbook`).
- **Description** — what the collection contains and when to use it.
- **Stats** — document count, chunk count, last updated timestamp.

### Documents & Chunks

Each collection contains **documents** (files, pages, articles). Documents are split into **chunks** — small passages optimized for semantic retrieval. When you search, results are returned at the chunk level with metadata pointing back to the source document.

### Versions

Some collections support **versioned documentation** (e.g., API docs v1.0, v2.0). Use `list_versions_{slug}()` or the API to discover available versions, then pass a `version` parameter to scope your search.

### Tags & Filters

Collections may support:

- **Custom tags** — string labels attached to documents (e.g., `["legal", "msa", "2024"]`). Pass as `custom_tags` to narrow results.
- **Filters** — key-value metadata filters (e.g., `{"region": "US", "department": "engineering"}`). Pass as `filters` to constrain results.

### Credits & Billing

- **Own collections and subscriptions** — free MCP/API access, no credit cost.
- **Marketplace products (pay-per-use)** — each retrieval deducts credits based on seller pricing.
- Credits are measured in USD. Check with `check_balance()` or `GET /v1/billing/balance`.
- Top up at `https://app.ragora.app/settings/billing`.

---

## Connection Setup

### Authentication

All requests (MCP and REST) require a Ragora API key.

- **Format**: `sk_live_<uuid>` (e.g., `sk_live_a1b2c3d4-e5f6-7890-abcd-ef1234567890`)
- **Create one**: `https://app.ragora.app/settings/api-keys`
- **Shown once** — copy and store it securely at creation time.
- **Hashed on server** — SHA-256 + bcrypt. Ragora cannot recover a lost key; generate a new one.

### Security rules

- Never pass API keys in URL query parameters.
- Never print full API keys in logs, outputs, or final answers.
- If the key is missing or invalid, stop and ask the user for a valid key.
- Mask keys in any debug output: `sk_live_****...`.

### MCP endpoint

- **URL**: `https://mcp.ragora.app/mcp`
- **Auth header**: `Authorization: Bearer <RAGORA_API_KEY>`

OpenClaw config (YAML):

```yaml
name: ragora
type: http
url: https://mcp.ragora.app/mcp
headers:
  Authorization: Bearer ${RAGORA_API_KEY}
```

Claude Desktop / Cursor / VS Code config (JSON):

```json
{
  "mcpServers": {
    "ragora": {
      "type": "http",
      "url": "https://mcp.ragora.app/mcp",
      "headers": {
        "Authorization": "Bearer ${RAGORA_API_KEY}"
      }
    }
  }
}
```

> **Security note**: Set `RAGORA_API_KEY` as an environment variable in your OS or secret manager. Never hardcode the raw `sk_live_*` value in config files that may be committed to version control.

### REST API base URL

- **Base**: `https://api.ragora.app/v1`
- **Auth header**: `Authorization: Bearer <RAGORA_API_KEY>`
- **Content-Type**: `application/json` for all POST/PUT requests.

---

## Connectivity Check (Run First)

### Via MCP

1. Confirm server health:

```bash
curl -s https://mcp.ragora.app/health
```

2. Call `discover_collections()`. If it returns collections, you're connected.

3. If empty — user may need to access a knowledge base: `https://ragora.app/marketplace`

4. If credits are low — call `check_balance()` and tell user to top up at `https://app.ragora.app/settings/billing`.

### Via REST API

1. Confirm server health:

```bash
curl -s https://api.ragora.app/v1/health
```

2. List collections:

```bash
curl https://api.ragora.app/v1/collections \
  -H "Authorization: Bearer <RAGORA_API_KEY>"
```

3. If the response is `401` or `403`, the API key is invalid or expired. Ask the user to generate a new one.

---

## Operating Rules

- Start with `discover_collections()` (MCP) or `GET /v1/collections` (API) before targeted retrieval, unless the user explicitly names a known collection.
- Prefer targeted collection search over global search once you know the likely collections.
- Use global search for broad exploration only — ambiguity, unknown source, or discovery pass.
- Keep retrieval iterative: run multiple focused queries instead of one long query.
- Include source attribution from returned results in final answers.
- Call out uncertainty when evidence is partial, conflicting, or missing.
- If credits are low or errors mention billing limits, check balance and report constraints.
- Choose MCP tools when available; fall back to REST API when MCP binding fails or when you need features not exposed via MCP (e.g., pagination, collection metadata).

---

## MCP Tools Reference

### Static tools (always available)

| Tool | Parameters | Description |
|------|-----------|-------------|
| `discover_collections()` | none | List all accessible knowledge bases with descriptions, stats, available operations, and usage examples. |
| `search(query, top_k?)` | `query` (required), `top_k` (1-20, default 5) | Search across ALL accessible collections at once. |
| `search_collection(collection_name, query, top_k?, custom_tags?, filters?)` | `collection_name` (required), `query` (required), `top_k` (1-20, default 5), `custom_tags` (list of strings), `filters` (object) | Search a specific collection by name or slug. |
| `check_balance()` | none | Credits remaining and estimated USD value. |

### Dynamic tools (per-collection, returned in manifest)

The Gateway generates these tools for each collection you have access to. The `{slug}` is the collection's URL-safe name (e.g., `employee_handbook`, `k8s_troubleshooting`).

| Tool | Parameters | Description |
|------|-----------|-------------|
| `search_{slug}(query, top_k?, version?, custom_tags?, filters?)` | `query` (required), `top_k` (1-20, default 5), `version` (optional string), `custom_tags` (list of strings), `filters` (object) | Semantic search within the collection. |
| `get_topic_{slug}(topic)` | `topic` (required string) | Retrieve information about a specific topic from the collection. |
| `list_versions_{slug}()` | none | List all available documentation versions for the collection. |

### MCP Resources

| URI | Description |
|-----|-------------|
| `ragora://collections` | Lists all accessible collections with metadata, stats, and available operations. |

### MCP Prompts

| Prompt | Parameters | Description |
|--------|-----------|-------------|
| `search_collection_prompt` | `collection_name`, `query` | Pre-built prompt for searching a specific collection. |
| `summarize_collection` | `collection_name` | Pre-built prompt for summarizing an entire collection. |
| `compare_sources` | `collection_names`, `question` | Pre-built prompt for comparing information across multiple collections. |

---

## REST API Reference

Use these endpoints when MCP tool binding is unavailable, or when you need direct HTTP control.

**All endpoints require**: `Authorization: Bearer <RAGORA_API_KEY>`

### Health check

```
GET https://api.ragora.app/v1/health
```

Response: `200 OK` with `{"status": "ok"}` if the service is up.

### List collections

```
GET https://api.ragora.app/v1/collections
```

Returns all collections accessible to the authenticated user.

Response:

```json
{
  "collections": [
    {
      "name": "Employee Handbook",
      "slug": "employee_handbook",
      "description": "Company policies, benefits, and procedures",
      "stats": {
        "document_count": 45,
        "chunk_count": 1230,
        "last_updated": "2025-11-15T08:30:00Z"
      },
      "supported_features": ["search", "get_topic", "versions", "filters"]
    }
  ]
}
```

### Search across all collections

```
POST https://api.ragora.app/v1/search
```

Request:

```json
{
  "query": "vacation policy for remote employees",
  "top_k": 5
}
```

Response:

```json
{
  "results": [
    {
      "content": "Remote employees are entitled to 20 days of paid vacation per year...",
      "score": 0.94,
      "source": {
        "collection": "employee_handbook",
        "document": "benefits-guide.md",
        "chunk_id": "ch_abc123"
      },
      "metadata": {}
    }
  ],
  "usage": {
    "cost_usd": 0.0,
    "balance_remaining_usd": 99.95
  }
}
```

### Search a specific collection

```
POST https://api.ragora.app/v1/collections/{slug}/search
```

Request:

```json
{
  "query": "log retention duration and deletion policy",
  "top_k": 5,
  "version": "2.0",
  "custom_tags": ["compliance", "soc2"],
  "filters": {
    "region": "US"
  }
}
```

Response: same structure as global search, but scoped to the named collection.

### Get topic from a collection

```
POST https://api.ragora.app/v1/collections/{slug}/topic
```

Request:

```json
{
  "topic": "remote work policy"
}
```

Response:

```json
{
  "content": "Detailed information about the remote work policy...",
  "source": {
    "collection": "employee_handbook",
    "document": "remote-work.md"
  },
  "usage": {
    "cost_usd": 0.0,
    "balance_remaining_usd": 99.95
  }
}
```

### List versions for a collection

```
GET https://api.ragora.app/v1/collections/{slug}/versions
```

Response:

```json
{
  "versions": [
    {"version": "2.0", "label": "v2.0 (latest)", "is_default": true},
    {"version": "1.5", "label": "v1.5", "is_default": false},
    {"version": "1.0", "label": "v1.0 (legacy)", "is_default": false}
  ]
}
```

### Check balance

```
GET https://api.ragora.app/v1/billing/balance
```

Response:

```json
{
  "credits_remaining": 9950,
  "estimated_usd": 99.50,
  "currency": "USD"
}
```

### MCP Gateway endpoints (tool proxy)

If you need to call MCP tools via REST (e.g., dynamic tools like `search_employee_handbook`):

**Get manifest** — lists all available MCP tools for your account:

```
GET https://api.ragora.app/v1/mcp/manifest
```

**Execute a tool** — call any MCP tool by name:

```
POST https://api.ragora.app/v1/mcp/execute
```

Request:

```json
{
  "tool": "search_employee_handbook",
  "arguments": {
    "query": "vacation policy",
    "top_k": 5
  }
}
```

Response:

```json
{
  "content": [
    {
      "type": "text",
      "text": "Found 5 results:\n\n1. **Vacation Policy** (score: 0.95)\n   Remote employees are entitled to...\n   Source: benefits-guide.md"
    }
  ],
  "usage": {
    "cost_usd": 0.0,
    "balance_remaining_usd": 99.95
  }
}
```

---

## Error Codes & Status Handling

### HTTP status codes

| Status | Meaning | Agent action |
|--------|---------|--------------|
| `200` | Success | Process results normally. |
| `400` | Bad request — malformed query, missing required param | Check request format. Fix the query and retry. |
| `401` | Unauthorized — missing or invalid API key | Stop. Ask the user to provide a valid `sk_live_` key. |
| `403` | Forbidden — key is valid but lacks access to this collection | Inform user they need to purchase/subscribe to this collection at the marketplace. |
| `404` | Not found — collection slug or endpoint doesn't exist | Check the slug with `discover_collections()` or `GET /v1/collections`. |
| `422` | Validation error — params are present but invalid (e.g., `top_k=50`) | Read the error message, fix the parameter, and retry. |
| `429` | Rate limited — too many requests | Wait and retry with exponential backoff (see Rate Limiting below). |
| `402` | Payment required — insufficient credits | Call `check_balance()`. Tell user to top up at billing page. |
| `500` | Server error | Retry once after 2 seconds. If it persists, inform user of a temporary service issue. |
| `503` | Service unavailable | Retry once after 5 seconds. If it persists, inform user. |

### Error response format

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Your balance is too low to complete this search. Current balance: $0.05.",
    "details": {}
  }
}
```

### Common error codes in response body

| Code | Description | Agent action |
|------|-------------|--------------|
| `invalid_api_key` | Key format wrong or key revoked | Ask user for a new key. |
| `expired_api_key` | Key has expired | Ask user to generate a new key at dashboard. |
| `insufficient_credits` | Not enough credits for this retrieval | Report balance and link to billing. |
| `collection_not_found` | Slug doesn't match any collection | Re-run discovery, check spelling. |
| `collection_access_denied` | User hasn't purchased access | Link user to the marketplace. |
| `rate_limit_exceeded` | Too many requests in window | Back off and retry. |
| `invalid_query` | Query is empty or too long | Fix and retry with a shorter, clearer query. |
| `version_not_found` | Requested version doesn't exist | Call `list_versions_{slug}()` to see valid versions. |

---

## Rate Limiting & Retry Strategy

### Limits

- **MCP tools**: 60 calls per minute per API key.
- **REST API**: 120 requests per minute per API key.
- Rate limit headers are returned on every response:
  - `X-RateLimit-Limit` — max requests in the window.
  - `X-RateLimit-Remaining` — requests left in the current window.
  - `X-RateLimit-Reset` — Unix timestamp when the window resets.

### Retry strategy

When you receive a `429` response:

1. Read the `Retry-After` header (seconds to wait) if present.
2. If no `Retry-After`, use exponential backoff: wait 1s, then 2s, then 4s.
3. Maximum 3 retries before giving up and informing the user.
4. Never retry `401` or `403` — these require user action, not waiting.

### Best practices to avoid rate limits

- Batch your queries logically: 3-5 focused queries per task, not 20 rapid-fire calls.
- Use `top_k=10-15` instead of making multiple `top_k=3` calls for the same question.
- Cache `discover_collections()` results within a session — collection lists rarely change mid-conversation.

---

## Authentication Troubleshooting

| Symptom | Likely cause | Fix |
|---------|-------------|-----|
| `401 Unauthorized` on every call | Missing or malformed `Authorization` header | Ensure header is exactly `Authorization: Bearer sk_live_xxxxx`. No extra spaces, no quotes around the token. |
| `401` but key looks correct | Key was revoked or regenerated | Ask user to check active keys at `https://app.ragora.app/settings/api-keys`. |
| `401` with `invalid_api_key` code | Key format is wrong (e.g., missing `sk_live_` prefix) | Verify format: must start with `sk_live_` followed by a UUID. |
| `401` with `expired_api_key` code | Key has an expiration and it passed | Generate a new key from the dashboard. |
| `403 Forbidden` | Key is valid but doesn't have access to the requested collection | User needs to purchase or subscribe to the collection. |
| MCP tools not appearing | MCP server not configured or wrong URL | Verify MCP URL is `https://mcp.ragora.app/mcp` and header is set. Run health check. |
| MCP tools appear but return errors | Key in MCP config is a placeholder | Replace `sk_live_xxx` with the actual key. |
| `ECONNREFUSED` or timeout | Network issue or service outage | Check `https://mcp.ragora.app/health`. If down, fall back to REST API or wait. |

---

## Core Workflow

### 1. Understand intent

- Classify request type: factual lookup, summary, comparison, extraction, or verification.
- Identify likely domains/collections from user wording.

### 2. Discover scope

- Run `discover_collections()` (MCP) or `GET /v1/collections` (API).
- Select 1-3 collections most relevant to the question.
- If no relevant collection exists, state that explicitly and stop.

### 3. Retrieve evidence

- **First pass**: one targeted query per selected collection.
- **Second pass**: refine with specific sub-queries (dates, entities, claims, thresholds).
- Tune `top_k` based on task:
  - `top_k=3-5` for direct factual questions.
  - `top_k=8-12` for comparisons or comprehensive summaries.
  - `top_k=15-20` for exhaustive research or due diligence.

### 4. Synthesize

- Merge evidence by claim, not by source order.
- Resolve conflicts by preferring direct passages and recency cues in content.
- Distinguish facts from inferences.

### 5. Respond

- Give a concise answer first.
- Then provide evidence bullets with collection/source references.
- End with gaps, caveats, or suggested follow-up queries when confidence is not high.

---

## Multi-Step Workflow Examples

### Research a topic across multiple collections

**Scenario**: User asks "What is our data retention policy and how does it compare to SOC 2 requirements?"

1. `discover_collections()` → find `security_handbook`, `compliance_docs`, `soc2_guide`
2. `search_collection("security_handbook", "data retention policy duration", top_k=5)`
3. `search_collection("compliance_docs", "SOC 2 data retention requirements", top_k=5)`
4. `search_collection("soc2_guide", "retention controls audit evidence", top_k=5)`
5. Synthesize: compare internal policy against SOC 2 requirements, note gaps.
6. Respond with findings, citing each collection.

### Compare two vendor contracts

**Scenario**: User asks "Compare the SLA terms between Vendor A and Vendor B."

1. `discover_collections()` → find `vendor_a_contract`, `vendor_b_contract`
2. `search_collection("vendor_a_contract", "SLA uptime guarantees penalties", top_k=8)`
3. `search_collection("vendor_b_contract", "SLA uptime guarantees penalties", top_k=8)`
4. Second pass for specifics:
   - `search_collection("vendor_a_contract", "termination notice period remedies", top_k=5)`
   - `search_collection("vendor_b_contract", "termination notice period remedies", top_k=5)`
5. Build comparison table: uptime %, penalty structure, notice periods, exclusions.
6. Highlight key differences and risks.

### Due diligence deep dive

**Scenario**: User asks "Summarize everything we know about Company X's security posture."

1. `search("Company X security audit penetration test vulnerability", top_k=15)` — broad discovery pass.
2. Identify which collections returned results (e.g., `due_diligence_reports`, `vendor_assessments`).
3. Targeted follow-up:
   - `search_collection("due_diligence_reports", "Company X SOC 2 ISO 27001 certifications", top_k=10)`
   - `search_collection("vendor_assessments", "Company X data encryption access controls", top_k=10)`
   - `search_collection("due_diligence_reports", "Company X incident history breach", top_k=5)`
4. Organize findings by category: certifications, technical controls, incident history, gaps.
5. Present with confidence levels and note areas with no data.

### Versioned documentation lookup

**Scenario**: User asks "What changed in the authentication flow between API v1 and v2?"

1. `list_versions_api_docs()` → returns `["1.0", "2.0"]`
2. `search_api_docs(query="authentication flow token exchange", version="1.0", top_k=5)`
3. `search_api_docs(query="authentication flow token exchange", version="2.0", top_k=5)`
4. Diff the results: what was added, changed, or removed.
5. Present a clear changelog-style summary.

### REST API workflow (no MCP)

**Scenario**: MCP binding is unavailable. User asks "Find our vacation policy."

1. Health check:
```bash
curl -s https://api.ragora.app/v1/health
```

2. List collections:
```bash
curl https://api.ragora.app/v1/collections \
  -H "Authorization: Bearer $RAGORA_API_KEY"
```

3. Search the relevant collection:
```bash
curl -X POST https://api.ragora.app/v1/collections/employee_handbook/search \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "vacation policy paid time off", "top_k": 5}'
```

4. Parse the `results` array, extract `content` and `source` fields, and compose the answer.

---

## Query Patterns

Use short, specific queries. Prefer multiple passes over one monolithic query.

### By task type

| Task | Query pattern | Example |
|------|--------------|---------|
| Factual lookup | `"<entity> <metric/attribute> <time period>"` | `"ACME Corp revenue 2024 Q3"` |
| Policy/requirements | `"<policy type> eligibility criteria exceptions"` | `"parental leave eligibility criteria exceptions"` |
| Comparison | Run same query across each collection | `"pricing limits SLA exclusions"` × 2 collections |
| Validation | First `"<claim>"`, then `"counterexample exception to <claim>"` | `"all employees get 20 vacation days"` then `"exceptions to vacation day policy"` |
| Extraction | `"<entity> <specific data point>"` | `"ACME Corp CEO contact information"` |
| Timeline | `"<entity> <event type> chronological"` | `"product launches timeline 2023 2024"` |

### Query refinement strategy

1. **Start broad**: `"data retention policy"` — see what's available.
2. **Narrow by entity**: `"customer data retention policy"` — scope to a specific domain.
3. **Narrow by attribute**: `"customer data retention duration deletion schedule"` — get specifics.
4. **Add constraints**: Use `filters` and `custom_tags` if results are noisy.

---

## Tooling Playbook

### Discover collections

MCP:
```text
discover_collections()
```

API:
```bash
curl https://api.ragora.app/v1/collections \
  -H "Authorization: Bearer $RAGORA_API_KEY"
```

### Broad search when unsure

MCP:
```text
search(query="SOC 2 retention policy for customer logs", top_k=8)
```

API:
```bash
curl -X POST https://api.ragora.app/v1/search \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "SOC 2 retention policy for customer logs", "top_k": 8}'
```

### Targeted collection search

MCP:
```text
search_collection(
  collection_name="security-handbook",
  query="log retention duration and deletion policy",
  top_k=5
)
```

API:
```bash
curl -X POST https://api.ragora.app/v1/collections/security_handbook/search \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "log retention duration and deletion policy", "top_k": 5}'
```

### Search with version

MCP:
```text
search_api_docs(
  query="authentication flow changes",
  version="2.0",
  top_k=5
)
```

API:
```bash
curl -X POST https://api.ragora.app/v1/collections/api_docs/search \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "authentication flow changes", "version": "2.0", "top_k": 5}'
```

### Get topic from a collection

MCP:
```text
get_topic_employee_handbook(topic="remote work policy")
```

API:
```bash
curl -X POST https://api.ragora.app/v1/collections/employee_handbook/topic \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"topic": "remote work policy"}'
```

### Filtered search

MCP:
```text
search_collection(
  collection_name="contracts",
  query="termination for convenience notice period",
  top_k=10,
  custom_tags=["msa", "legal"],
  filters={"region": "US"}
)
```

API:
```bash
curl -X POST https://api.ragora.app/v1/collections/contracts/search \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "termination for convenience notice period", "top_k": 10, "custom_tags": ["msa", "legal"], "filters": {"region": "US"}}'
```

### Credit check

MCP:
```text
check_balance()
```

API:
```bash
curl https://api.ragora.app/v1/billing/balance \
  -H "Authorization: Bearer $RAGORA_API_KEY"
```

### Compare across collections

MCP prompt:
```text
compare_sources(
  collection_names=["vendor-a-docs", "vendor-b-docs"],
  question="What are the SLA differences?"
)
```

API (manual — run two searches and compare):
```bash
# Search vendor A
curl -X POST https://api.ragora.app/v1/collections/vendor_a_docs/search \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "SLA uptime guarantees penalties", "top_k": 8}'

# Search vendor B
curl -X POST https://api.ragora.app/v1/collections/vendor_b_docs/search \
  -H "Authorization: Bearer $RAGORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "SLA uptime guarantees penalties", "top_k": 8}'
```

---

## Context Management

### Choosing `top_k`

| Scenario | Recommended `top_k` | Rationale |
|----------|---------------------|-----------|
| Simple factual question | 3-5 | Few precise results keep context small. |
| Multi-facet question | 5-8 | Need coverage across sub-topics. |
| Comparison across collections | 8-12 per collection | Need enough evidence from each side. |
| Exhaustive research / due diligence | 15-20 | Comprehensive coverage at the cost of more context. |
| Quick validation of a claim | 2-3 | Just need to confirm or deny. |

### Managing context window size

- **Prefer targeted searches over global searches.** `search_collection()` returns fewer, more relevant results than `search()`.
- **Summarize as you go.** After retrieving results, extract the key facts before moving to the next query. Don't accumulate raw results.
- **Use multi-pass retrieval.** First pass: broad query with `top_k=5`. Read results. Second pass: specific follow-up queries targeting gaps.
- **Drop low-relevance results.** If a result has a low relevance score or doesn't relate to the question, ignore it.
- **Don't retrieve what you already know.** If a previous query already answered part of the question, don't re-query for it.

### When results are too large

If a single query returns more text than is useful:

1. Reduce `top_k` to 3.
2. Add `custom_tags` or `filters` to narrow scope.
3. Use a more specific query instead of a broad one.
4. Focus on the highest-scoring results and discard the rest.

### When results are insufficient

If a query returns no results or irrelevant results:

1. Broaden the query: remove specific terms, use synonyms.
2. Try global `search()` instead of collection-specific.
3. Check if the collection exists with `discover_collections()`.
4. Try a different collection if multiple are available.
5. If still empty, tell the user that no relevant data was found.

---

## Output Formatting Guidelines

### Standard response structure

```
**Answer**: <2-6 sentence direct answer>

**Evidence**:
- <claim> — *<collection_name> / <source_document>*
- <claim> — *<collection_name> / <source_document>*
- <claim> — *<collection_name> / <source_document>*

**Caveats**:
- <what is missing, uncertain, or conflicting>

**Suggested follow-ups** (if applicable):
- <exact query the user could ask next>
```

### Source citation rules

- Always cite the **collection name** and **source document** for every claim.
- Format: `— *Collection Name / document-name.md*`
- If multiple results support the same claim, cite the highest-scoring one.
- If results conflict, cite both and note the conflict.

### Confidence indicators

- **High confidence**: multiple results agree, high relevance scores (>0.85), from authoritative collections.
- **Medium confidence**: single result or moderate scores (0.6-0.85). Note: "Based on a single source."
- **Low confidence**: low scores (<0.6), tangential results, or inferred conclusions. Note: "This is inferred and may need verification."

### Comparison format

When comparing across collections, use a table:

```
| Aspect | Vendor A | Vendor B |
|--------|----------|----------|
| Uptime SLA | 99.9% | 99.95% |
| Penalty | 5% credit per hour | 10% credit per hour |
| Notice period | 30 days | 60 days |

*Sources: vendor_a_contract/sla.md, vendor_b_contract/sla.md*
```

---

## Failure Handling

| Failure | Agent action |
|---------|-------------|
| **No results** | Broaden wording, remove overly specific constraints, retry with `search()`. If still empty, inform user. |
| **Too many noisy results** | Constrain by collection, add `custom_tags`/`filters`, use narrower entity/date terms. |
| **Conflicting evidence** | Present both sides, note the conflict, cite both sources, and propose a follow-up query to resolve. |
| **Access denied (403)** | Explain that collection access may need to be purchased. Link to marketplace. |
| **Credit errors (402)** | Run `check_balance()`, report the balance, and link to billing page. |
| **Rate limited (429)** | Wait per `Retry-After` header or use exponential backoff. Max 3 retries. |
| **Server error (500/503)** | Retry once after 2-5 seconds. If it persists, inform user of a temporary issue. |
| **MCP connection failure** | Fall back to REST API endpoints. Inform user of the switch. |
| **Timeout** | Reduce `top_k`, simplify the query, and retry. |
| **Invalid collection slug** | Re-run `discover_collections()` and check available slugs. |

---

## Quality Bar

- Never fabricate unseen facts — all claims must come from retrieved evidence.
- Always ground claims in retrieved evidence with source citations.
- Prefer precise wording over broad generalization.
- Keep final responses concise, decision-oriented, and source-backed.
- Distinguish between directly stated facts and inferred conclusions.
- When evidence is incomplete, explicitly state what is missing rather than guessing.
- If a question cannot be answered from available collections, say so directly.

Example Workflow

Here's how your AI assistant might use this skill in practice.

INPUT

User asks: Finding internal HR or remote work policies across company handbooks

AGENT
  1. 1Finding internal HR or remote work policies across company handbooks
  2. 2Comparing SLA terms and penalty clauses between two vendor contracts
  3. 3Researching a company's security certifications and past audit history
  4. 4Looking up what changed between two versions of an API's authentication flow
  5. 5Verifying a compliance claim against SOC 2 documentation
OUTPUT
Use Ragora MCP tools and REST API to discover, search, and synthesize answers from knowledge bases.

Share this skill

Security Audits

VirusTotalBenign
OpenClawBenign
View full report

These signals reflect official OpenClaw status values. A Suspicious status means the skill should be used with extra caution.

Details

LanguageMarkdown
Last updatedFeb 25, 2026