ragora
by @mregmi
Use Ragora MCP tools and REST API to discover, search, and synthesize answers from knowledge bases. Trigger when the user asks for grounded answers from Ragora collections, cross-collection comparison, source-backed summaries, due diligence research, or verification using marketplace data.
clawhub install ragoraπ About This Skill
name: ragora description: Use Ragora MCP tools and REST API to discover, search, and synthesize answers from knowledge bases. Trigger when the user asks for grounded answers from Ragora collections, cross-collection comparison, source-backed summaries, due diligence research, or verification using marketplace data. metadata: {"openclaw": {"emoji": "π", "homepage": "https://github.com/velarynai/ragora-openclaw", "requires": {"env": ["RAGORA_API_KEY"]}, "primaryEnv": "RAGORA_API_KEY"}}
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:
https://ragora.app/docs?section=mcp-guidehttps://ragora.app/docs?section=getting-startedhttps://ragora.app/docs?section=api-overviewhttps://ragora.app/docs?section=api-retrievehttps://ragora.app/docs?section=api-errorshttps://ragora.app/docs?section=api-billingCore 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:
employee_handbook).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:
["legal", "msa", "2024"]). Pass as custom_tags to narrow results.{"region": "US", "department": "engineering"}). Pass as filters to constrain results.Credits & Billing
check_balance() or GET /v1/billing/balance.https://app.ragora.app/settings/billing.Connection Setup
Authentication
All requests (MCP and REST) require a Ragora API key.
sk_live_ (e.g., sk_live_a1b2c3d4-e5f6-7890-abcd-ef1234567890)https://app.ragora.app/settings/api-keysSecurity rules
sk_live_****....MCP endpoint
https://mcp.ragora.app/mcpAuthorization: Bearer OpenClaw config (YAML):
name: ragora
type: http
url: https://mcp.ragora.app/mcp
headers:
Authorization: Bearer ${RAGORA_API_KEY}
Claude Desktop / Cursor / VS Code config (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
https://api.ragora.app/v1Authorization: Bearer application/json for all POST/PUT requests.Connectivity Check (Run First)
Via MCP
1. Confirm server health:
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:
curl -s https://api.ragora.app/v1/health
2. List collections:
curl https://api.ragora.app/v1/collections \
-H "Authorization: Bearer "
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
discover_collections() (MCP) or GET /v1/collections (API) before targeted retrieval, unless the user explicitly names a known collection.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
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:
{
"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:
{
"query": "vacation policy for remote employees",
"top_k": 5
}
Response:
{
"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:
{
"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:
{
"topic": "remote work policy"
}
Response:
{
"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:
{
"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:
{
"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:
{
"tool": "search_employee_handbook",
"arguments": {
"query": "vacation policy",
"top_k": 5
}
}
Response:
{
"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
{
"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
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
top_k=10-15 instead of making multiple top_k=3 calls for the same question.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
2. Discover scope
discover_collections() (MCP) or GET /v1/collections (API).3. Retrieve evidence
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
5. Respond
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:
curl -s https://api.ragora.app/v1/health
2. List collections:
curl https://api.ragora.app/v1/collections \
-H "Authorization: Bearer $RAGORA_API_KEY"
3. Search the relevant collection:
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 | " | "ACME Corp revenue 2024 Q3" |
| Policy/requirements | " | "parental leave eligibility criteria exceptions" |
| Comparison | Run same query across each collection | "pricing limits SLA exclusions" Γ 2 collections |
| Validation | First ", then "counterexample exception to | "all employees get 20 vacation days" then "exceptions to vacation day policy" |
| Extraction | " | "ACME Corp CEO contact information" |
| Timeline | " | "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:
discover_collections()
API:
curl https://api.ragora.app/v1/collections \
-H "Authorization: Bearer $RAGORA_API_KEY"
Broad search when unsure
MCP:
search(query="SOC 2 retention policy for customer logs", top_k=8)
API:
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:
search_collection(
collection_name="security-handbook",
query="log retention duration and deletion policy",
top_k=5
)
API:
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:
search_api_docs(
query="authentication flow changes",
version="2.0",
top_k=5
)
API:
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:
get_topic_employee_handbook(topic="remote work policy")
API:
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:
search_collection(
collection_name="contracts",
query="termination for convenience notice period",
top_k=10,
custom_tags=["msa", "legal"],
filters={"region": "US"}
)
API:
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:
check_balance()
API:
curl https://api.ragora.app/v1/billing/balance \
-H "Authorization: Bearer $RAGORA_API_KEY"
Compare across collections
MCP prompt:
compare_sources(
collection_names=["vendor-a-docs", "vendor-b-docs"],
question="What are the SLA differences?"
)
API (manual β run two searches and compare):
# 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
search_collection() returns fewer, more relevant results than search().top_k=5. Read results. Second pass: specific follow-up queries targeting gaps.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:
β * / *
β * / *
β * / * Caveats:
Suggested follow-ups (if applicable):
Source citation rules
β *Collection Name / document-name.md*Confidence indicators
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. |