mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-26 15:40:18 +00:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67d5a47333 | ||
|
|
62ea08ac5e | ||
|
|
5cb073de72 | ||
|
|
5563b53e52 | ||
|
|
4d643f47c7 | ||
|
|
a12188e231 | ||
|
|
6d6b7fab0e | ||
|
|
7018ddafab | ||
|
|
84b182b7e2 | ||
|
|
2ce6e785e7 | ||
|
|
85bcaa64e9 | ||
|
|
ae0cae3a22 |
@@ -24,6 +24,7 @@ E2E tests: see `tests/e2e/CLAUDE.md`.
|
||||
- Prefer strong types over strings (enums, newtypes)
|
||||
- Keep functions focused, extract helpers when logic is reused
|
||||
- Comments for non-obvious logic only
|
||||
- **Prompt templates live in files, not Rust code**: Multi-line prompt strings (mission goals, system prompts, CodeAct preambles) go in `crates/ironclaw_engine/prompts/*.md` and are loaded via `include_str!()`. Never inline large prompt templates as Rust string constants — they're hard to read, review, and iterate on. Single-line format strings are fine inline.
|
||||
- **Logging levels matter for REPL/TUI**: `info!` and `warn!` output appears in the REPL and corrupts the terminal UI. Use `debug!` for internal diagnostics (trace analysis, reflection results, engine internals). Reserve `info!` for user-facing status that the REPL intentionally renders. Background tasks (reflection, trace analysis) must NEVER use `info!` — it breaks the interactive display.
|
||||
|
||||
## Architecture
|
||||
@@ -36,7 +37,7 @@ All I/O is async with tokio. Use `Arc<T>` for shared state, `RwLock` for concurr
|
||||
|
||||
## Extracted Crates
|
||||
|
||||
Safety logic lives in `crates/ironclaw_safety/`. The `src/safety/mod.rs` shim re-exports everything for backward compatibility, but **new code should import from `ironclaw_safety` directly** (e.g. `use ironclaw_safety::SafetyLayer`). When touching a file that still uses `crate::safety::*`, migrate its imports to `ironclaw_safety::*`.
|
||||
Safety logic lives in `crates/ironclaw_safety/`, skills in `crates/ironclaw_skills/`. **Import directly from the extracted crate** (e.g. `use ironclaw_safety::SafetyLayer`, `use ironclaw_skills::SkillRegistry`). Do not use `crate::safety::` or `crate::skills::` for types that originate in extracted crates — `src/safety/mod.rs` and `src/skills/mod.rs` no longer glob-re-export. Local items defined in those modules (e.g. `crate::skills::attenuate_tools`) are fine.
|
||||
|
||||
## Project Structure
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use criterion::{Criterion, black_box, criterion_group, criterion_main};
|
||||
use ironclaw::safety::{LeakDetector, Sanitizer, Validator};
|
||||
use ironclaw_safety::{LeakDetector, Sanitizer, Validator};
|
||||
|
||||
fn bench_sanitizer(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("sanitizer");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use criterion::{Criterion, black_box, criterion_group, criterion_main};
|
||||
use ironclaw::config::SafetyConfig;
|
||||
use ironclaw::safety::{SafetyLayer, Validator};
|
||||
use ironclaw_safety::{SafetyLayer, Validator};
|
||||
|
||||
fn bench_safety_layer_pipeline(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("safety_pipeline");
|
||||
|
||||
@@ -181,6 +181,14 @@ pub enum AppEvent {
|
||||
thread_id: Option<String>,
|
||||
},
|
||||
|
||||
/// Skills activated for a conversation turn.
|
||||
#[serde(rename = "skill_activated")]
|
||||
SkillActivated {
|
||||
skill_names: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
thread_id: Option<String>,
|
||||
},
|
||||
|
||||
/// Extension activation status change (WASM channels).
|
||||
#[serde(rename = "extension_status")]
|
||||
ExtensionStatus {
|
||||
@@ -260,6 +268,7 @@ impl AppEvent {
|
||||
Self::ImageGenerated { .. } => "image_generated",
|
||||
Self::Suggestions { .. } => "suggestions",
|
||||
Self::TurnCost { .. } => "turn_cost",
|
||||
Self::SkillActivated { .. } => "skill_activated",
|
||||
Self::ExtensionStatus { .. } => "extension_status",
|
||||
Self::ReasoningUpdate { .. } => "reasoning_update",
|
||||
Self::JobReasoning { .. } => "job_reasoning",
|
||||
@@ -381,6 +390,10 @@ mod tests {
|
||||
cost_usd: String::new(),
|
||||
thread_id: None,
|
||||
},
|
||||
AppEvent::SkillActivated {
|
||||
skill_names: vec![],
|
||||
thread_id: None,
|
||||
},
|
||||
AppEvent::ExtensionStatus {
|
||||
extension_name: String::new(),
|
||||
status: String::new(),
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# Monty Integration
|
||||
|
||||
Monty is the embedded Python interpreter used for Tier 1 (CodeAct) execution. It's a lightweight Rust-native Python implementation — not CPython — so it has a restricted feature set.
|
||||
|
||||
**Source**: `git = "https://github.com/pydantic/monty.git", branch = "main"`
|
||||
**Pinned at**: `6053820` (2026-03-27, "Support max() kwargs/default")
|
||||
|
||||
## Upgrade Process
|
||||
|
||||
1. **Update the pin**: `cargo update -p monty`
|
||||
2. **Check for new features**: `cd ~/.cargo/git/checkouts/monty-*/*/` and `git log --oneline` since last pin
|
||||
3. **Update the preamble**: If a previously-unsupported feature now works, remove it from the "Runtime environment" section in `prompts/codeact_preamble.md`
|
||||
4. **Update this file**: Record the new pin and what changed
|
||||
5. **Run tests**: `cargo test -p ironclaw_engine`
|
||||
6. **Watch traces**: After deploying, check traces for new `NotImplementedError` patterns (self-improvement mission catches these)
|
||||
|
||||
## Current Limitations (as of pin `6053820`)
|
||||
|
||||
These are documented in `prompts/codeact_preamble.md` so the LLM avoids them:
|
||||
|
||||
### Syntax not supported
|
||||
| Feature | Workaround |
|
||||
|---------|-----------|
|
||||
| `import a, b, c` (multi-module) | Use separate `import a` / `import b` statements |
|
||||
| `class Foo:` | Use functions and dicts |
|
||||
| `with` statements | Use try/finally or direct calls |
|
||||
| `match` statements | Use if/elif chains |
|
||||
| `del` statement | Reassign to None |
|
||||
| `yield` / `yield from` | Use lists and list comprehensions |
|
||||
| `*expr` (starred expressions) | Unpack explicitly |
|
||||
| `async` / `await` | Not available; tool calls suspend the VM automatically |
|
||||
| Type aliases (`type X = ...`) | Omit type annotations |
|
||||
| Template strings (t-strings) | Use f-strings |
|
||||
| Complex number literals | Use floats |
|
||||
| Exception groups (`try*/except*`) | Use regular try/except |
|
||||
|
||||
### No standard library
|
||||
`import datetime`, `import csv`, `import json`, `import os`, `import io`, etc. all fail.
|
||||
|
||||
Available built-in modules:
|
||||
- `math` — standard math functions
|
||||
- `re` — regex (basic)
|
||||
- `sys` — system info (limited)
|
||||
- `os.path` — path manipulation (limited)
|
||||
- `typing` — type hints (limited, for annotation only)
|
||||
|
||||
### Available builtins
|
||||
`abs`, `all`, `any`, `bin`, `chr`, `divmod`, `enumerate`, `filter`, `getattr`, `hash`, `hex`, `id`, `isinstance`, `len`, `map`, `min`, `max`, `next`, `oct`, `ord`, `pow`, `print`, `repr`, `reversed`, `round`, `sorted`, `sum`, `type`, `zip`
|
||||
|
||||
### Host-provided functions (always available)
|
||||
These are injected by the IronClaw executor, not by Monty:
|
||||
- `FINAL(answer)` / `FINAL_VAR(name)` — terminate with result
|
||||
- `llm_query(prompt, context)` — recursive LLM sub-call
|
||||
- `llm_query_batched(prompts)` — parallel sub-calls
|
||||
- `rlm_query(prompt)` — full sub-agent with tools
|
||||
- `globals()` / `locals()` — returns dict of known tool names
|
||||
- All tool functions (web_search, http, time, etc.)
|
||||
|
||||
## Upgrade Changelog
|
||||
|
||||
| Date | Pin | Notable changes |
|
||||
|------|-----|-----------------|
|
||||
| 2026-03-20 | `6053820` | Initial integration. max() kwargs support. |
|
||||
@@ -266,6 +266,9 @@ def run_loop(context, goal, actions, state, config):
|
||||
if active_skills:
|
||||
skill_text = format_skills(active_skills)
|
||||
__add_message__("system_append", skill_text)
|
||||
# Emit skill activation event for CLI/gateway display
|
||||
skill_names = ",".join(s.get("metadata", {}).get("name", "?") for s in active_skills)
|
||||
__emit_event__("skill_activated", skill_names=skill_names)
|
||||
# Store active skill IDs in state for tracking
|
||||
state["active_skill_ids"] = [s.get("doc_id", "") for s in active_skills]
|
||||
state["skill_snippet_names"] = []
|
||||
@@ -336,6 +339,7 @@ def run_loop(context, goal, actions, state, config):
|
||||
"nudge_count": nudge_count,
|
||||
"consecutive_errors": consecutive_errors,
|
||||
})
|
||||
__transition_to__("waiting", "approval needed")
|
||||
return {
|
||||
"outcome": "need_approval",
|
||||
"action_name": approval.get("action_name", ""),
|
||||
@@ -379,6 +383,7 @@ def run_loop(context, goal, actions, state, config):
|
||||
"nudge_count": nudge_count,
|
||||
"consecutive_errors": consecutive_errors,
|
||||
})
|
||||
__transition_to__("waiting", "approval needed")
|
||||
return {
|
||||
"outcome": "need_approval",
|
||||
"action_name": name,
|
||||
|
||||
@@ -40,3 +40,20 @@ You can write multiple code blocks across turns. Variables persist between block
|
||||
6. For large data, process it in chunks using llm_query() on subsets rather than loading everything into context.
|
||||
7. Outputs are truncated to 8000 chars — use variables to store large intermediate results.
|
||||
8. Include the actual content in your FINAL() answer, not just a count or summary. Users want to see the details.
|
||||
|
||||
## Runtime environment
|
||||
|
||||
The Python REPL runs in Monty, a lightweight embedded interpreter — not CPython. Key differences:
|
||||
|
||||
- **No standard library modules**: `import datetime`, `import csv`, `import json`, `import os`, `import re` etc. will fail with `ModuleNotFoundError`. Use the provided tool functions instead (e.g. `time()` for dates, `http()` for fetching data, `json()` for parsing).
|
||||
- **Single imports only**: `import a, b, c` is not supported. Use separate statements: `import a` then `import b`.
|
||||
- **No classes**: `class Foo:` is not supported. Use functions and dicts instead.
|
||||
- **No `with` statements**: Use try/finally or just call functions directly.
|
||||
- **No `match` statements**: Use if/elif chains.
|
||||
- **No `del` statement**: Reassign to None instead.
|
||||
- **No `yield`/`yield from`**: Use lists and list comprehensions instead of generators.
|
||||
- **No `*expr` unpacking in assignments**: Unpack explicitly.
|
||||
- **Available builtins**: `abs`, `all`, `any`, `bin`, `chr`, `divmod`, `enumerate`, `filter`, `getattr`, `hash`, `hex`, `id`, `isinstance`, `len`, `map`, `min`, `max`, `next`, `oct`, `ord`, `pow`, `print`, `repr`, `reversed`, `round`, `sorted`, `sum`, `type`, `zip`.
|
||||
- **Available modules**: `math`, `re`, `sys`, `os.path`, `typing` (limited).
|
||||
- **String methods, list methods, dict methods**: All work normally.
|
||||
- For dates, use the `time()` tool. For CSV parsing, split strings manually. For HTTP, use `http()`. For JSON, use `json()` or work with dicts directly (tool results are already Python objects).
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
You extract user preferences, patterns, and domain knowledge from a batch of recent conversation threads.
|
||||
|
||||
## Input
|
||||
|
||||
`state["trigger_payload"]` contains:
|
||||
- `project_id` — the project scope
|
||||
- `completed_thread_count` — total threads completed in this conversation
|
||||
- `thread_goals` — list of recent thread goals (what the user asked for)
|
||||
- `sample_user_messages` — sample of actual user messages (truncated to 200 chars)
|
||||
|
||||
## Process
|
||||
|
||||
1. Analyze the thread goals and user messages for patterns
|
||||
2. Search existing insights: `memory_search(query="user preferences")` and `memory_search(query="domain knowledge")`
|
||||
3. Extract NEW insights not already recorded in memory
|
||||
4. Write each insight to memory via `memory_write(target="memory", content=insight_text)` with title format "insight:<category>:<topic>"
|
||||
|
||||
## Categories to look for
|
||||
|
||||
- **Preferences**: communication style, format choices, tool preferences
|
||||
- **Domain**: project names, API patterns, data formats, technology stack
|
||||
- **Workflow**: recurring task sequences, common follow-up questions
|
||||
- **Corrections**: things the user corrected or repeated — these signal unmet expectations
|
||||
|
||||
## Output (FINAL)
|
||||
|
||||
Report:
|
||||
- Number of new insights extracted (0 is fine)
|
||||
- Brief list of what was found
|
||||
- Next focus
|
||||
|
||||
## Rules
|
||||
|
||||
- Only record actionable, specific insights — not vague observations
|
||||
- Do not record personal information, only work patterns
|
||||
- If no meaningful new insights after analysis, call FINAL("No new insights — conversation patterns already captured") immediately
|
||||
- Merge with existing insight docs rather than creating duplicates
|
||||
- Max 5 insights per run to keep quality high
|
||||
@@ -0,0 +1,58 @@
|
||||
You investigate why IronClaw did not behave as the user expected. The user used the `/expected` command to describe what should have happened, and the trigger payload includes the recent conversation turns showing what actually happened.
|
||||
|
||||
## Input
|
||||
|
||||
`state["trigger_payload"]` contains:
|
||||
- `expected_behavior` — what the user expected to happen (their description)
|
||||
- `thread_id` — the conversation thread where the issue occurred
|
||||
- `recent_turns` — list of recent turns, each with:
|
||||
- `user_input` — what the user asked
|
||||
- `response` — what the agent responded
|
||||
- `tool_calls` — list of tools called (with name and any errors)
|
||||
- `state` — turn completion state
|
||||
- `error` — any error message
|
||||
|
||||
## Investigation process
|
||||
|
||||
1. **Understand the gap**: Compare `expected_behavior` against `recent_turns`. What did the user want? What actually happened? Be precise about the delta.
|
||||
|
||||
2. **Classify the root cause**:
|
||||
- MISSING_CAPABILITY: The agent doesn't have the tool or integration needed (e.g. no GitHub OAuth, no API key configured)
|
||||
- WRONG_TOOL_CHOICE: The agent had the right tools but chose the wrong one or didn't use them at all
|
||||
- PROMPT_GAP: The agent didn't know the right approach because the system prompt lacks guidance for this scenario
|
||||
- CONFIG_ISSUE: A timeout, limit, or default prevented success
|
||||
- BUG: Actual code error in tool execution or response processing
|
||||
|
||||
3. **Apply a fix** based on classification:
|
||||
|
||||
MISSING_CAPABILITY:
|
||||
- Search for relevant skills: `skill_search(query="...")` or `tool_search(query="...")`
|
||||
- If a skill/tool exists but isn't installed, note it as a recommendation
|
||||
- If nothing exists, add a prompt rule acknowledging the limitation and suggesting alternatives the user can take
|
||||
|
||||
WRONG_TOOL_CHOICE or PROMPT_GAP:
|
||||
- Apply a Level 1 (prompt overlay) fix — add a rule that guides the agent in this scenario
|
||||
- Use `memory_write` with title="prompt:codeact_preamble" and tags=["prompt_overlay"]
|
||||
- The rule must be specific and actionable
|
||||
|
||||
CONFIG_ISSUE:
|
||||
- Diagnose via `read_file` and `shell` commands
|
||||
- Apply Level 2 fix if safe (branch, change, test, commit)
|
||||
|
||||
BUG:
|
||||
- Read relevant source files to understand the issue
|
||||
- Propose a Level 3 fix (describe but don't apply)
|
||||
|
||||
4. **Record** in FINAL():
|
||||
- What the user expected vs what happened (one sentence each)
|
||||
- Root cause classification
|
||||
- What fix was applied (or recommended)
|
||||
- Next focus
|
||||
|
||||
## Rules
|
||||
|
||||
- The user's expectation is the ground truth — don't argue with it
|
||||
- If multiple issues exist, fix the most impactful one first
|
||||
- Be specific in prompt rules ("When asked to file a GitHub issue, use the http tool with the GitHub API" is good; "Try harder" is useless)
|
||||
- If the gap is a missing credential or integration, say so clearly — don't pretend the capability exists
|
||||
- Max one fix per run
|
||||
@@ -0,0 +1,67 @@
|
||||
You are a self-improvement agent for the IronClaw engine. You receive trigger payloads containing execution trace issues from completed threads. Your job is to diagnose root causes and apply fixes so the same issue doesn't recur.
|
||||
|
||||
## What you have access to
|
||||
|
||||
- `state["trigger_payload"]` — JSON with `issues` (list of {severity, category, description, step}), `error_messages` (actual error text from failed actions), `goal` (what the thread was trying to do), and `source_thread_id`.
|
||||
- All tools: shell, read_file, write_file, apply_patch, web_search, memory_write, etc.
|
||||
- The codebase at the current working directory.
|
||||
- The fix pattern database in prior knowledge (if loaded).
|
||||
|
||||
## The experiment loop
|
||||
|
||||
For each issue in the trigger payload:
|
||||
|
||||
1. **Diagnose**: Read the error messages and issue descriptions. Classify the root cause:
|
||||
- PROMPT: The LLM made a mistake because the system prompt is missing a rule (wrong tool name, bad API usage, ignoring tool results)
|
||||
- CONFIG: A default value is wrong (truncation length, iteration limit, timeout)
|
||||
- CODE: There is a bug in the engine or bridge code (crash, type error, missing conversion)
|
||||
|
||||
2. **Check the fix pattern database** in prior knowledge. Has this pattern been seen before? If yes, apply the known strategy. If no, proceed to step 3.
|
||||
|
||||
3. **Apply the fix** based on the level:
|
||||
|
||||
Level 1 (PROMPT — low risk, apply directly):
|
||||
- Read the current prompt overlay: `memory_search("prompt:codeact_preamble")`
|
||||
- Write an updated overlay with a new rule appended
|
||||
- Use `memory_write` with title="prompt:codeact_preamble" and tags=["prompt_overlay"]
|
||||
- The rule should be specific and actionable (e.g. "Never call web_fetch — use http() instead")
|
||||
|
||||
Level 2 (CONFIG — medium risk):
|
||||
- Use `read_file` to find the relevant constant or default
|
||||
- Use `shell` to create a git branch: `git checkout -b self-improve/issue-description`
|
||||
- Apply the change with `apply_patch` or `write_file`
|
||||
- Run tests: `cargo test -p ironclaw_engine`
|
||||
- If tests pass, commit. If not, revert: `git checkout main`
|
||||
|
||||
Level 3 (CODE — high risk, just propose):
|
||||
- Read the relevant source files
|
||||
- Describe the fix needed but DO NOT apply it directly
|
||||
- Log it as a recommendation in your FINAL() response
|
||||
|
||||
4. **Record what you did** — include in your FINAL() response:
|
||||
- What issue you analyzed
|
||||
- What level fix you applied (1/2/3)
|
||||
- What specific change you made
|
||||
- Next focus: what to look for next time
|
||||
|
||||
## Important rules
|
||||
|
||||
- Be specific. "Never call web_fetch" is good. "Be careful with tool names" is useless.
|
||||
- One fix per issue. Don't try to fix everything at once.
|
||||
- For Level 1 fixes, the rule must be one sentence that can be appended to the prompt.
|
||||
- If the trigger payload has no actionable issues (only Info severity), skip and call FINAL() immediately.
|
||||
- NEVER modify test files to make a fix pass.
|
||||
- NEVER modify security-sensitive code (safety layer, policy engine, leak detection).
|
||||
- If you can't diagnose the root cause after reading the errors, log it and move on.
|
||||
|
||||
## Level 1.5: Orchestrator patches (medium risk, auto-rollback)
|
||||
|
||||
The execution loop itself is Python code that you can modify. This is the orchestrator — it handles tool dispatch, output formatting, state management, and context building. If the bug is in the glue between the LLM and tools (wrong output format, bad truncation, missing state), you can patch it directly.
|
||||
|
||||
To modify the orchestrator:
|
||||
1. Read current version: `memory_search("orchestrator:main")`
|
||||
2. Make your change (keep it minimal — one fix at a time)
|
||||
3. Save the new version: `memory_write` with title="orchestrator:main", tags=["orchestrator_code"], metadata={"version": N+1, "parent_version": N}
|
||||
4. The next thread will use your updated orchestrator
|
||||
|
||||
If your change causes 3 consecutive failures, the system auto-rolls back to the previous version. So be conservative — test your logic mentally before saving.
|
||||
@@ -0,0 +1,69 @@
|
||||
You extract reusable skills from successfully completed multi-step threads.
|
||||
|
||||
## Input
|
||||
|
||||
`state["trigger_payload"]` contains:
|
||||
- `source_thread_id` — the thread that completed successfully
|
||||
- `goal` — what the thread accomplished
|
||||
- `step_count` — number of execution steps
|
||||
- `action_count` — number of tool actions executed
|
||||
- `actions_used` — list of tool names used
|
||||
- `total_tokens` — tokens consumed
|
||||
|
||||
## Output Format
|
||||
|
||||
Save as a Skill memory doc via `memory_write(target="memory", content=skill_prompt)` with:
|
||||
- title: `"skill:<short-name>"` (e.g., "skill:github-issue-triage")
|
||||
- doc_type: `"skill"`
|
||||
- metadata JSON:
|
||||
```json
|
||||
{
|
||||
"name": "<short-name>",
|
||||
"version": 1,
|
||||
"description": "<one-line description>",
|
||||
"activation": {
|
||||
"keywords": ["<keyword1>", "<keyword2>"],
|
||||
"patterns": ["<optional regex>"],
|
||||
"tags": ["<domain-tag>"],
|
||||
"exclude_keywords": [],
|
||||
"max_context_tokens": <estimated budget, e.g. 1000>
|
||||
},
|
||||
"source": "extracted",
|
||||
"trust": "trusted",
|
||||
"code_snippets": [
|
||||
{
|
||||
"name": "<function_name>",
|
||||
"code": "def <function_name>(...):\n ...",
|
||||
"description": "<what it does>"
|
||||
}
|
||||
],
|
||||
"metrics": {"usage_count": 0, "success_count": 0, "failure_count": 0},
|
||||
"content_hash": ""
|
||||
}
|
||||
```
|
||||
|
||||
## Process
|
||||
|
||||
1. Search for the source thread's context: `memory_search(query=goal)`
|
||||
2. Check for existing skills: `memory_search(query="skill:")`
|
||||
3. If a similar skill exists, update it (increment version) rather than creating a duplicate
|
||||
4. Extract:
|
||||
- Activation keywords from the goal + user messages (be specific, not generic)
|
||||
- Step-by-step instructions as the prompt content
|
||||
- Python code snippets for CodeAct (reusable functions using exact tool names)
|
||||
- Domain tags (e.g., "github", "api", "data")
|
||||
|
||||
## Output (FINAL)
|
||||
|
||||
Report what you did:
|
||||
- The skill title and a one-line summary
|
||||
- Whether it is new or an update to an existing skill
|
||||
- Next focus: what patterns to watch for
|
||||
|
||||
## Rules
|
||||
|
||||
- Only extract skills from threads with 3+ distinct tool calls
|
||||
- Keywords must be specific (not generic words like "help", "do", "make")
|
||||
- Code snippets must use exact tool function names as they appear in the thread
|
||||
- If the thread was a trivial query-response, call FINAL("No skill needed — simple interaction") and stop immediately
|
||||
- One skill per FINAL — do not combine unrelated procedures
|
||||
@@ -81,5 +81,4 @@ mod tests {
|
||||
assert_eq!(plans[0].capability_name, "tools");
|
||||
assert_eq!(plans[0].granted_actions, vec!["read_file"]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -147,8 +147,8 @@ impl SkillTracker {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::project::ProjectId;
|
||||
use ironclaw_skills::v2::{SkillMetrics, V2SkillSource};
|
||||
use ironclaw_skills::SkillTrust;
|
||||
use ironclaw_skills::v2::{SkillMetrics, V2SkillSource};
|
||||
|
||||
fn make_skill_doc(project_id: ProjectId) -> MemoryDoc {
|
||||
let meta = V2SkillMetadata {
|
||||
@@ -169,8 +169,12 @@ mod tests {
|
||||
content_hash: String::new(),
|
||||
};
|
||||
|
||||
let mut doc =
|
||||
MemoryDoc::new(project_id, DocType::Skill, "skill:test", "Test skill prompt");
|
||||
let mut doc = MemoryDoc::new(
|
||||
project_id,
|
||||
DocType::Skill,
|
||||
"skill:test",
|
||||
"Test skill prompt",
|
||||
);
|
||||
doc.metadata = serde_json::to_value(&meta).unwrap();
|
||||
doc
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ pub struct ExecutionLoop {
|
||||
retrieval: Option<crate::memory::RetrievalEngine>,
|
||||
/// Optional Store for runtime prompt overlay loading and skill retrieval.
|
||||
store: Option<Arc<dyn crate::traits::store::Store>>,
|
||||
/// Runtime platform metadata for self-awareness in system prompts.
|
||||
platform_info: Option<crate::executor::prompt::PlatformInfo>,
|
||||
}
|
||||
|
||||
impl ExecutionLoop {
|
||||
@@ -74,6 +76,7 @@ impl ExecutionLoop {
|
||||
event_tx: None,
|
||||
retrieval: None,
|
||||
store: None,
|
||||
platform_info: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +110,12 @@ impl ExecutionLoop {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set platform metadata for self-awareness in system prompts.
|
||||
pub fn with_platform_info(mut self, info: crate::executor::prompt::PlatformInfo) -> Self {
|
||||
self.platform_info = Some(info);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add an event to the thread and broadcast it for live status updates.
|
||||
#[allow(dead_code)]
|
||||
fn emit_event(&mut self, kind: EventKind) {
|
||||
@@ -232,6 +241,7 @@ impl ExecutionLoop {
|
||||
&actions,
|
||||
self.store.as_ref(),
|
||||
self.thread.project_id,
|
||||
self.platform_info.as_ref(),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -295,6 +305,22 @@ impl ExecutionLoop {
|
||||
.await;
|
||||
}
|
||||
let _ = &orch_result.tokens_used;
|
||||
|
||||
// Safety net: if the orchestrator returned NeedApproval but
|
||||
// didn't transition to Waiting, do it now so resume_thread works.
|
||||
if matches!(orch_result.outcome, ThreadOutcome::NeedApproval { .. })
|
||||
&& self.thread.state != ThreadState::Waiting
|
||||
{
|
||||
debug!(
|
||||
thread_id = %self.thread.id,
|
||||
state = ?self.thread.state,
|
||||
"orchestrator returned NeedApproval without transitioning to Waiting"
|
||||
);
|
||||
let _ = self
|
||||
.thread
|
||||
.transition_to(ThreadState::Waiting, Some("approval needed".into()));
|
||||
}
|
||||
|
||||
self.clear_runtime_checkpoint();
|
||||
self.persist_runtime_state(None, &mut persisted_event_count)
|
||||
.await?;
|
||||
@@ -1201,7 +1227,10 @@ mod tests {
|
||||
|
||||
assert!(!exec_events.is_empty(), "should have ActionExecuted events");
|
||||
for call_id in &exec_events {
|
||||
assert!(!call_id.is_empty(), "ActionExecuted event must have non-empty call_id");
|
||||
assert!(
|
||||
!call_id.is_empty(),
|
||||
"ActionExecuted event must have non-empty call_id"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1247,20 +1276,11 @@ mod tests {
|
||||
let policy = Arc::new(PolicyEngine::new());
|
||||
|
||||
// Grant a lease that does NOT cover "restricted_tool"
|
||||
leases
|
||||
.grant(tid, "basic_cap", vec![], None, None)
|
||||
.await;
|
||||
leases.grant(tid, "basic_cap", vec![], None, None).await;
|
||||
|
||||
let (_tx, rx) = crate::runtime::messaging::signal_channel(16);
|
||||
let mut exec = ExecutionLoop::new(
|
||||
thread,
|
||||
llm,
|
||||
effects,
|
||||
leases,
|
||||
policy,
|
||||
rx,
|
||||
"test-user".into(),
|
||||
);
|
||||
let mut exec =
|
||||
ExecutionLoop::new(thread, llm, effects, leases, policy, rx, "test-user".into());
|
||||
|
||||
exec.run().await.unwrap();
|
||||
|
||||
@@ -1296,10 +1316,7 @@ mod tests {
|
||||
.collect();
|
||||
|
||||
for (call_id, _name) in &fail_events {
|
||||
assert!(
|
||||
!call_id.is_empty(),
|
||||
"ActionFailed event must have call_id"
|
||||
);
|
||||
assert!(!call_id.is_empty(), "ActionFailed event must have call_id");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ use crate::traits::effect::{EffectExecutor, ThreadExecutionContext};
|
||||
use crate::traits::llm::{LlmBackend, LlmCallConfig};
|
||||
use crate::traits::store::Store;
|
||||
use crate::types::error::EngineError;
|
||||
use crate::types::event::{EventKind, ThreadEvent};
|
||||
use crate::types::event::{EventKind, ThreadEvent, summarize_params};
|
||||
use crate::types::message::ThreadMessage;
|
||||
use crate::types::project::ProjectId;
|
||||
use crate::types::step::{StepId, TokenUsage};
|
||||
@@ -334,8 +334,10 @@ pub async fn execute_orchestrator(
|
||||
|
||||
// __execute_code_step__(code, state)
|
||||
"__execute_code_step__" => {
|
||||
handle_execute_code_step(args, kwargs, thread, llm, effects, leases, policy)
|
||||
.await
|
||||
handle_execute_code_step(
|
||||
args, kwargs, thread, llm, effects, leases, policy, event_tx,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
// __execute_action__(name, params, call_id=...)
|
||||
@@ -373,14 +375,10 @@ pub async fn execute_orchestrator(
|
||||
"__get_actions__" => handle_get_actions(thread, effects, leases).await,
|
||||
|
||||
// __list_skills__(max_candidates, max_tokens)
|
||||
"__list_skills__" => {
|
||||
handle_list_skills(args, thread, store).await
|
||||
}
|
||||
"__list_skills__" => handle_list_skills(args, thread, store).await,
|
||||
|
||||
// __record_skill_usage__(doc_id, success)
|
||||
"__record_skill_usage__" => {
|
||||
handle_record_skill_usage(args, store).await
|
||||
}
|
||||
"__record_skill_usage__" => handle_record_skill_usage(args, store).await,
|
||||
|
||||
// Unknown — let Monty resolve it (user-defined functions, builtins)
|
||||
other => ExtFunctionResult::NotFound(other.to_string()),
|
||||
@@ -539,14 +537,16 @@ async fn handle_llm_complete(
|
||||
///
|
||||
/// Runs user CodeAct code in a nested Monty VM with full tool dispatch.
|
||||
/// Returns a dict with stdout, return_value, action_results, etc.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn handle_execute_code_step(
|
||||
args: &[MontyObject],
|
||||
_kwargs: &[(MontyObject, MontyObject)],
|
||||
thread: &Thread,
|
||||
thread: &mut Thread,
|
||||
llm: &Arc<dyn LlmBackend>,
|
||||
effects: &Arc<dyn EffectExecutor>,
|
||||
leases: &Arc<LeaseManager>,
|
||||
policy: &Arc<PolicyEngine>,
|
||||
event_tx: Option<&tokio::sync::broadcast::Sender<ThreadEvent>>,
|
||||
) -> ExtFunctionResult {
|
||||
let code = match args.first() {
|
||||
Some(obj) => monty_to_string(obj),
|
||||
@@ -586,6 +586,18 @@ async fn handle_execute_code_step(
|
||||
.await
|
||||
{
|
||||
Ok(result) => {
|
||||
// Broadcast events from code execution to the thread and event channel.
|
||||
// Without this, ActionExecuted events from CodeAct tool calls are lost
|
||||
// and never appear in traces.
|
||||
for event_kind in &result.events {
|
||||
let event = ThreadEvent::new(thread.id, event_kind.clone());
|
||||
if let Some(tx) = event_tx {
|
||||
let _ = tx.send(event.clone());
|
||||
}
|
||||
thread.events.push(event);
|
||||
}
|
||||
thread.updated_at = chrono::Utc::now();
|
||||
|
||||
let action_results: Vec<serde_json::Value> = result
|
||||
.action_results
|
||||
.iter()
|
||||
@@ -686,7 +698,11 @@ async fn handle_execute_action(
|
||||
}
|
||||
thread.events.push(event);
|
||||
thread.updated_at = chrono::Utc::now();
|
||||
thread.add_message(ThreadMessage::action_result(call_id, action_name, output.to_string()));
|
||||
thread.add_message(ThreadMessage::action_result(
|
||||
call_id,
|
||||
action_name,
|
||||
output.to_string(),
|
||||
));
|
||||
};
|
||||
|
||||
// 1. Find lease for this action
|
||||
@@ -703,6 +719,7 @@ async fn handle_execute_action(
|
||||
action_name: name.clone(),
|
||||
call_id: call_id.clone(),
|
||||
error,
|
||||
params_summary: None,
|
||||
},
|
||||
&call_id,
|
||||
&name,
|
||||
@@ -735,6 +752,7 @@ async fn handle_execute_action(
|
||||
action_name: name.clone(),
|
||||
call_id: call_id.clone(),
|
||||
error: reason,
|
||||
params_summary: None,
|
||||
},
|
||||
&call_id,
|
||||
&name,
|
||||
@@ -763,6 +781,7 @@ async fn handle_execute_action(
|
||||
}
|
||||
|
||||
// 4. Execute
|
||||
let ps = summarize_params(&name, ¶ms);
|
||||
match effects
|
||||
.execute_action(&name, params, &lease, &exec_ctx)
|
||||
.await
|
||||
@@ -776,6 +795,7 @@ async fn handle_execute_action(
|
||||
action_name: name.clone(),
|
||||
call_id: call_id.clone(),
|
||||
duration_ms: r.duration.as_millis() as u64,
|
||||
params_summary: ps.clone(),
|
||||
},
|
||||
&call_id,
|
||||
&name,
|
||||
@@ -799,6 +819,7 @@ async fn handle_execute_action(
|
||||
action_name: name.clone(),
|
||||
call_id: call_id.clone(),
|
||||
error: e.to_string(),
|
||||
params_summary: ps,
|
||||
},
|
||||
&call_id,
|
||||
&name,
|
||||
@@ -870,6 +891,7 @@ fn handle_emit_event(
|
||||
action_name,
|
||||
call_id,
|
||||
duration_ms: 0,
|
||||
params_summary: None,
|
||||
}
|
||||
}
|
||||
"action_failed" => {
|
||||
@@ -881,8 +903,18 @@ fn handle_emit_event(
|
||||
action_name,
|
||||
call_id,
|
||||
error,
|
||||
params_summary: None,
|
||||
}
|
||||
}
|
||||
"skill_activated" => {
|
||||
let names_str = extract_string_kwarg(kwargs, "skill_names").unwrap_or_default();
|
||||
let skill_names: Vec<String> = names_str
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty())
|
||||
.collect();
|
||||
EventKind::SkillActivated { skill_names }
|
||||
}
|
||||
_ => {
|
||||
debug!(kind = %kind_str, "orchestrator: unknown event kind, skipping");
|
||||
return ExtFunctionResult::Return(MontyObject::None);
|
||||
|
||||
@@ -14,6 +14,64 @@ use crate::traits::store::Store;
|
||||
use crate::types::capability::ActionDef;
|
||||
use crate::types::project::ProjectId;
|
||||
|
||||
/// Runtime platform metadata injected into system prompts for self-awareness.
|
||||
///
|
||||
/// Provides the agent with knowledge about its own identity and environment
|
||||
/// so it can answer questions about itself, its capabilities, and its
|
||||
/// configuration without relying on training data.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct PlatformInfo {
|
||||
/// Software version (from CARGO_PKG_VERSION).
|
||||
pub version: Option<String>,
|
||||
/// LLM backend name (e.g. "nearai", "openai", "anthropic").
|
||||
pub llm_backend: Option<String>,
|
||||
/// Active model name.
|
||||
pub model_name: Option<String>,
|
||||
/// Database backend (e.g. "libsql", "postgres").
|
||||
pub database_backend: Option<String>,
|
||||
/// Active channel names (e.g. ["telegram", "cli"]).
|
||||
pub active_channels: Vec<String>,
|
||||
/// Owner identifier.
|
||||
pub owner_id: Option<String>,
|
||||
/// Project repository URL.
|
||||
pub repo_url: Option<String>,
|
||||
}
|
||||
|
||||
impl PlatformInfo {
|
||||
/// Format as a prompt section. Returns empty string if no info is set.
|
||||
pub fn to_prompt_section(&self) -> String {
|
||||
let mut lines = Vec::new();
|
||||
|
||||
lines.push("You are **IronClaw**, a secure autonomous AI assistant platform.".into());
|
||||
if let Some(ref v) = self.version {
|
||||
lines.push(format!("- Version: {v}"));
|
||||
}
|
||||
if let Some(ref repo) = self.repo_url {
|
||||
lines.push(format!("- Repository: {repo}"));
|
||||
}
|
||||
if let Some(ref owner) = self.owner_id {
|
||||
lines.push(format!("- Owner: {owner}"));
|
||||
}
|
||||
if let Some(ref backend) = self.llm_backend {
|
||||
let model = self.model_name.as_deref().unwrap_or("default");
|
||||
lines.push(format!("- LLM: {backend} ({model})"));
|
||||
}
|
||||
if let Some(ref db) = self.database_backend {
|
||||
lines.push(format!("- Database: {db}"));
|
||||
}
|
||||
if !self.active_channels.is_empty() {
|
||||
lines.push(format!("- Channels: {}", self.active_channels.join(", ")));
|
||||
}
|
||||
|
||||
if lines.len() <= 1 {
|
||||
// Only the identity line, no runtime details — still include it
|
||||
return format!("\n\n## Platform\n\n{}\n", lines[0]);
|
||||
}
|
||||
|
||||
format!("\n\n## Platform\n\n{}\n", lines.join("\n"))
|
||||
}
|
||||
}
|
||||
|
||||
/// The main instruction block (before tool listing).
|
||||
const CODEACT_PREAMBLE: &str = include_str!("../../prompts/codeact_preamble.md");
|
||||
|
||||
@@ -46,9 +104,15 @@ pub async fn build_codeact_system_prompt(
|
||||
actions: &[ActionDef],
|
||||
store: Option<&Arc<dyn Store>>,
|
||||
project_id: ProjectId,
|
||||
platform: Option<&PlatformInfo>,
|
||||
) -> String {
|
||||
let mut prompt = String::from(CODEACT_PREAMBLE);
|
||||
|
||||
// Inject platform identity and runtime metadata
|
||||
if let Some(info) = platform {
|
||||
prompt.push_str(&info.to_prompt_section());
|
||||
}
|
||||
|
||||
// Append runtime prompt overlay if available
|
||||
if let Some(store) = store
|
||||
&& let Some(overlay) = load_prompt_overlay(store, project_id).await
|
||||
@@ -102,7 +166,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn prompt_without_store_uses_compiled_preamble() {
|
||||
let prompt = build_codeact_system_prompt(&[], None, ProjectId(uuid::Uuid::nil())).await;
|
||||
let prompt =
|
||||
build_codeact_system_prompt(&[], None, ProjectId(uuid::Uuid::nil()), None).await;
|
||||
assert!(prompt.contains("Python REPL environment"));
|
||||
assert!(prompt.contains("Strategy"));
|
||||
assert!(!prompt.contains("Learned Rules"));
|
||||
@@ -126,7 +191,8 @@ mod tests {
|
||||
|
||||
let store = Arc::new(crate::tests::InMemoryStore::with_docs(vec![overlay]));
|
||||
let prompt =
|
||||
build_codeact_system_prompt(&[], Some(&(store as Arc<dyn Store>)), project_id).await;
|
||||
build_codeact_system_prompt(&[], Some(&(store as Arc<dyn Store>)), project_id, None)
|
||||
.await;
|
||||
assert!(prompt.contains("Learned Rules"));
|
||||
assert!(prompt.contains("Never call web_fetch"));
|
||||
}
|
||||
@@ -152,7 +218,8 @@ mod tests {
|
||||
|
||||
let store = Arc::new(crate::tests::InMemoryStore::with_docs(vec![overlay]));
|
||||
let prompt =
|
||||
build_codeact_system_prompt(&[], Some(&(store as Arc<dyn Store>)), project_id).await;
|
||||
build_codeact_system_prompt(&[], Some(&(store as Arc<dyn Store>)), project_id, None)
|
||||
.await;
|
||||
|
||||
let snowman_count = prompt.chars().filter(|c| *c == '\u{2603}').count();
|
||||
assert_eq!(snowman_count, MAX_PROMPT_OVERLAY_CHARS);
|
||||
@@ -177,8 +244,39 @@ mod tests {
|
||||
|
||||
let store = Arc::new(crate::tests::InMemoryStore::with_docs(vec![overlay]));
|
||||
let prompt =
|
||||
build_codeact_system_prompt(&[], Some(&(store as Arc<dyn Store>)), project_id).await;
|
||||
build_codeact_system_prompt(&[], Some(&(store as Arc<dyn Store>)), project_id, None)
|
||||
.await;
|
||||
assert!(!prompt.contains("Should not appear"));
|
||||
assert!(!prompt.contains("Learned Rules"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn prompt_with_platform_info_injects_identity() {
|
||||
let info = PlatformInfo {
|
||||
version: Some("1.2.3".into()),
|
||||
llm_backend: Some("nearai".into()),
|
||||
model_name: Some("qwen3-235b".into()),
|
||||
database_backend: Some("libsql".into()),
|
||||
active_channels: vec!["telegram".into(), "cli".into()],
|
||||
owner_id: Some("alice.near".into()),
|
||||
repo_url: Some("https://github.com/nearai/ironclaw".into()),
|
||||
};
|
||||
let prompt =
|
||||
build_codeact_system_prompt(&[], None, ProjectId(uuid::Uuid::nil()), Some(&info)).await;
|
||||
assert!(prompt.contains("IronClaw"));
|
||||
assert!(prompt.contains("1.2.3"));
|
||||
assert!(prompt.contains("nearai"));
|
||||
assert!(prompt.contains("qwen3-235b"));
|
||||
assert!(prompt.contains("libsql"));
|
||||
assert!(prompt.contains("telegram"));
|
||||
assert!(prompt.contains("alice.near"));
|
||||
assert!(prompt.contains("github.com/nearai/ironclaw"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn prompt_without_platform_info_has_no_platform_section() {
|
||||
let prompt =
|
||||
build_codeact_system_prompt(&[], None, ProjectId(uuid::Uuid::nil()), None).await;
|
||||
assert!(!prompt.contains("## Platform"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,6 +437,18 @@ pub async fn execute_code_with_skills(
|
||||
.await
|
||||
}
|
||||
|
||||
// globals() / locals() — return dict with known names so
|
||||
// `"tool_name" in globals()` works for capability probing
|
||||
"globals" | "locals" => {
|
||||
let entries: Vec<(MontyObject, MontyObject)> = known_actions
|
||||
.iter()
|
||||
.map(|name| {
|
||||
(MontyObject::String(name.clone()), MontyObject::Bool(true))
|
||||
})
|
||||
.collect();
|
||||
ExtFunctionResult::Return(MontyObject::Dict(entries.into()))
|
||||
}
|
||||
|
||||
// Regular tool dispatch
|
||||
_ => {
|
||||
let dispatch = dispatch_action(
|
||||
@@ -518,6 +530,13 @@ pub async fn execute_code_with_skills(
|
||||
name: name.clone(),
|
||||
docstring: None,
|
||||
})
|
||||
} else if name == "globals" || name == "locals" {
|
||||
// Python builtins for namespace introspection — resolve as
|
||||
// callable so code like `"tool" in globals()` works.
|
||||
NameLookupResult::Value(MontyObject::Function {
|
||||
name: name.clone(),
|
||||
docstring: None,
|
||||
})
|
||||
} else {
|
||||
debug!(name = %name, "Monty: unresolved name");
|
||||
NameLookupResult::Undefined
|
||||
@@ -971,6 +990,7 @@ async fn dispatch_action(
|
||||
action_name: action_name.into(),
|
||||
call_id: call_id.into(),
|
||||
error: format!("no lease for action '{action_name}'"),
|
||||
params_summary: None,
|
||||
});
|
||||
return DispatchResult::Ok(ExtFunctionResult::NotFound(action_name.into()));
|
||||
}
|
||||
@@ -990,6 +1010,7 @@ async fn dispatch_action(
|
||||
action_name: action_name.into(),
|
||||
call_id: call_id.into(),
|
||||
error: reason.clone(),
|
||||
params_summary: None,
|
||||
});
|
||||
return DispatchResult::Ok(ExtFunctionResult::Error(MontyException::new(
|
||||
ExcType::RuntimeError,
|
||||
@@ -1014,6 +1035,8 @@ async fn dispatch_action(
|
||||
)));
|
||||
}
|
||||
|
||||
let ps = crate::types::event::summarize_params(action_name, ¶ms);
|
||||
|
||||
match effects
|
||||
.execute_action(action_name, params, &lease, context)
|
||||
.await
|
||||
@@ -1024,6 +1047,7 @@ async fn dispatch_action(
|
||||
action_name: action_name.into(),
|
||||
call_id: call_id.into(),
|
||||
duration_ms: result.duration.as_millis() as u64,
|
||||
params_summary: ps,
|
||||
});
|
||||
let monty_obj = json_to_monty(&result.output);
|
||||
action_results.push(result);
|
||||
@@ -1042,6 +1066,7 @@ async fn dispatch_action(
|
||||
action_name: action_name.into(),
|
||||
call_id: call_id.into(),
|
||||
error: e.to_string(),
|
||||
params_summary: ps,
|
||||
});
|
||||
DispatchResult::Ok(ExtFunctionResult::Error(MontyException::new(
|
||||
ExcType::RuntimeError,
|
||||
|
||||
@@ -68,6 +68,7 @@ pub async fn execute_action_calls(
|
||||
action_name: call.action_name.clone(),
|
||||
call_id: call.id.clone(),
|
||||
error: format!("no lease for action '{}'", call.action_name),
|
||||
params_summary: None,
|
||||
});
|
||||
results.push(error_result);
|
||||
continue;
|
||||
@@ -97,6 +98,7 @@ pub async fn execute_action_calls(
|
||||
action_name: call.action_name.clone(),
|
||||
call_id: call.id.clone(),
|
||||
error: reason,
|
||||
params_summary: None,
|
||||
});
|
||||
results.push(error_result);
|
||||
continue;
|
||||
@@ -138,9 +140,35 @@ pub async fn execute_action_calls(
|
||||
action_name: call.action_name.clone(),
|
||||
call_id: call.id.clone(),
|
||||
duration_ms: action_result.duration.as_millis() as u64,
|
||||
params_summary: None,
|
||||
});
|
||||
results.push(action_result);
|
||||
}
|
||||
Err(crate::types::error::EngineError::NeedAuthentication {
|
||||
credential_name,
|
||||
action_name,
|
||||
call_id,
|
||||
parameters,
|
||||
}) => {
|
||||
// Interrupt the batch — thread should pause for authentication.
|
||||
events.push(EventKind::ActionFailed {
|
||||
step_id: context.step_id,
|
||||
action_name: action_name.clone(),
|
||||
call_id: call_id.clone(),
|
||||
error: format!("authentication required for credential '{credential_name}'"),
|
||||
params_summary: None,
|
||||
});
|
||||
return Ok(ActionBatchResult {
|
||||
results,
|
||||
events,
|
||||
need_approval: Some(ThreadOutcome::NeedAuthentication {
|
||||
credential_name,
|
||||
action_name,
|
||||
call_id,
|
||||
parameters,
|
||||
}),
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
let error_result = ActionResult {
|
||||
call_id: call.id.clone(),
|
||||
@@ -154,6 +182,7 @@ pub async fn execute_action_calls(
|
||||
action_name: call.action_name.clone(),
|
||||
call_id: call.id.clone(),
|
||||
error: e.to_string(),
|
||||
params_summary: None,
|
||||
});
|
||||
results.push(error_result);
|
||||
}
|
||||
@@ -248,7 +277,12 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn call_id_preserved_on_successful_execution() {
|
||||
let thread = Thread::new("test", ThreadType::Foreground, ProjectId::new(), ThreadConfig::default());
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("web_search")],
|
||||
vec![Ok(ActionResult {
|
||||
@@ -282,9 +316,17 @@ mod tests {
|
||||
assert!(!result.results[0].is_error);
|
||||
|
||||
// Event should carry the same call_id
|
||||
let exec_event = result.events.iter().find(|e| matches!(e, EventKind::ActionExecuted { .. }));
|
||||
let exec_event = result
|
||||
.events
|
||||
.iter()
|
||||
.find(|e| matches!(e, EventKind::ActionExecuted { .. }));
|
||||
assert!(exec_event.is_some());
|
||||
if let Some(EventKind::ActionExecuted { call_id, action_name, .. }) = exec_event {
|
||||
if let Some(EventKind::ActionExecuted {
|
||||
call_id,
|
||||
action_name,
|
||||
..
|
||||
}) = exec_event
|
||||
{
|
||||
assert_eq!(call_id, "call_r2o5mqBgdNUlH8KzskncUGaX");
|
||||
assert_eq!(action_name, "web_search");
|
||||
}
|
||||
@@ -292,7 +334,12 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn call_id_preserved_on_execution_error() {
|
||||
let thread = Thread::new("test", ThreadType::Foreground, ProjectId::new(), ThreadConfig::default());
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("shell")],
|
||||
vec![Err(EngineError::Effect {
|
||||
@@ -319,7 +366,10 @@ mod tests {
|
||||
assert_eq!(result.results[0].call_id, "call_abc123def");
|
||||
assert!(result.results[0].is_error);
|
||||
|
||||
let fail_event = result.events.iter().find(|e| matches!(e, EventKind::ActionFailed { .. }));
|
||||
let fail_event = result
|
||||
.events
|
||||
.iter()
|
||||
.find(|e| matches!(e, EventKind::ActionFailed { .. }));
|
||||
assert!(fail_event.is_some());
|
||||
if let Some(EventKind::ActionFailed { call_id, .. }) = fail_event {
|
||||
assert_eq!(call_id, "call_abc123def");
|
||||
@@ -328,7 +378,12 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn call_id_preserved_when_no_lease() {
|
||||
let thread = Thread::new("test", ThreadType::Foreground, ProjectId::new(), ThreadConfig::default());
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(vec![], vec![]));
|
||||
let leases = Arc::new(LeaseManager::new());
|
||||
let policy = Arc::new(PolicyEngine::new());
|
||||
@@ -359,7 +414,12 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn multiple_calls_each_get_correct_call_id() {
|
||||
let thread = Thread::new("test", ThreadType::Foreground, ProjectId::new(), ThreadConfig::default());
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("tool_a"), test_action("tool_b")],
|
||||
vec![
|
||||
@@ -407,11 +467,197 @@ mod tests {
|
||||
assert_eq!(result.results[1].call_id, "id_bbbb");
|
||||
}
|
||||
|
||||
// ── NeedAuthentication tests ─────────────────────────────
|
||||
|
||||
#[tokio::test]
|
||||
async fn need_authentication_interrupts_batch() {
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("http")],
|
||||
vec![Err(EngineError::NeedAuthentication {
|
||||
credential_name: "github_token".into(),
|
||||
action_name: "http".into(),
|
||||
call_id: "call_auth_1".into(),
|
||||
parameters: serde_json::json!({"url": "https://api.github.com/repos"}),
|
||||
})],
|
||||
));
|
||||
let leases = Arc::new(LeaseManager::new());
|
||||
let policy = Arc::new(PolicyEngine::new());
|
||||
let ctx = make_exec_context(&thread);
|
||||
|
||||
leases.grant(thread.id, "tools", vec![], None, None).await;
|
||||
|
||||
let calls = vec![ActionCall {
|
||||
id: "call_auth_1".into(),
|
||||
action_name: "http".into(),
|
||||
parameters: serde_json::json!({"url": "https://api.github.com/repos"}),
|
||||
}];
|
||||
|
||||
let result = execute_action_calls(&calls, &thread, &effects, &leases, &policy, &ctx, &[])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Batch should be interrupted with NeedAuthentication outcome
|
||||
assert!(
|
||||
result.need_approval.is_some(),
|
||||
"NeedAuthentication should interrupt the batch"
|
||||
);
|
||||
match result.need_approval.unwrap() {
|
||||
ThreadOutcome::NeedAuthentication {
|
||||
credential_name,
|
||||
action_name,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(credential_name, "github_token");
|
||||
assert_eq!(action_name, "http");
|
||||
}
|
||||
other => panic!("expected NeedAuthentication, got {:?}", other),
|
||||
}
|
||||
|
||||
// ActionFailed event should be emitted
|
||||
assert!(
|
||||
result
|
||||
.events
|
||||
.iter()
|
||||
.any(|e| matches!(e, EventKind::ActionFailed { .. })),
|
||||
"should emit ActionFailed event"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn need_authentication_stops_before_subsequent_calls() {
|
||||
// Two calls: first needs auth, second should never execute
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("http"), test_action("echo")],
|
||||
vec![
|
||||
Err(EngineError::NeedAuthentication {
|
||||
credential_name: "api_key".into(),
|
||||
action_name: "http".into(),
|
||||
call_id: "call_1".into(),
|
||||
parameters: serde_json::json!({}),
|
||||
}),
|
||||
// This should never be called
|
||||
Ok(ActionResult {
|
||||
call_id: String::new(),
|
||||
action_name: "echo".into(),
|
||||
output: serde_json::json!("should not appear"),
|
||||
is_error: false,
|
||||
duration: Duration::from_millis(1),
|
||||
}),
|
||||
],
|
||||
));
|
||||
let leases = Arc::new(LeaseManager::new());
|
||||
let policy = Arc::new(PolicyEngine::new());
|
||||
let ctx = make_exec_context(&thread);
|
||||
|
||||
leases.grant(thread.id, "tools", vec![], None, None).await;
|
||||
|
||||
let calls = vec![
|
||||
ActionCall {
|
||||
id: "call_1".into(),
|
||||
action_name: "http".into(),
|
||||
parameters: serde_json::json!({}),
|
||||
},
|
||||
ActionCall {
|
||||
id: "call_2".into(),
|
||||
action_name: "echo".into(),
|
||||
parameters: serde_json::json!({}),
|
||||
},
|
||||
];
|
||||
|
||||
let result = execute_action_calls(&calls, &thread, &effects, &leases, &policy, &ctx, &[])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Second call should NOT have executed
|
||||
assert!(
|
||||
result.results.is_empty(),
|
||||
"no results should be returned before the interrupted call"
|
||||
);
|
||||
assert!(result.need_approval.is_some());
|
||||
}
|
||||
|
||||
/// Regular EngineError::Effect (not NeedAuthentication) should NOT interrupt —
|
||||
/// it becomes a normal error result and execution continues.
|
||||
#[tokio::test]
|
||||
async fn regular_effect_error_does_not_interrupt() {
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("http"), test_action("echo")],
|
||||
vec![
|
||||
Err(EngineError::Effect {
|
||||
reason: "connection timeout".into(),
|
||||
}),
|
||||
Ok(ActionResult {
|
||||
call_id: String::new(),
|
||||
action_name: "echo".into(),
|
||||
output: serde_json::json!("second call ran"),
|
||||
is_error: false,
|
||||
duration: Duration::from_millis(1),
|
||||
}),
|
||||
],
|
||||
));
|
||||
let leases = Arc::new(LeaseManager::new());
|
||||
let policy = Arc::new(PolicyEngine::new());
|
||||
let ctx = make_exec_context(&thread);
|
||||
|
||||
leases.grant(thread.id, "tools", vec![], None, None).await;
|
||||
|
||||
let calls = vec![
|
||||
ActionCall {
|
||||
id: "call_1".into(),
|
||||
action_name: "http".into(),
|
||||
parameters: serde_json::json!({}),
|
||||
},
|
||||
ActionCall {
|
||||
id: "call_2".into(),
|
||||
action_name: "echo".into(),
|
||||
parameters: serde_json::json!({}),
|
||||
},
|
||||
];
|
||||
|
||||
let result = execute_action_calls(&calls, &thread, &effects, &leases, &policy, &ctx, &[])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Both calls should have results (error does not interrupt)
|
||||
assert_eq!(result.results.len(), 2);
|
||||
assert!(result.results[0].is_error);
|
||||
assert!(!result.results[1].is_error);
|
||||
assert!(
|
||||
result.need_approval.is_none(),
|
||||
"no interruption for regular errors"
|
||||
);
|
||||
}
|
||||
|
||||
// ── call_id preservation (OpenAI/Mistral) ─────────────────
|
||||
|
||||
/// Provider-specific: OpenAI rejects empty string call_id. Verify no result
|
||||
/// ever has an empty call_id when the ActionCall provided one.
|
||||
#[tokio::test]
|
||||
async fn openai_empty_call_id_never_produced() {
|
||||
let thread = Thread::new("test", ThreadType::Foreground, ProjectId::new(), ThreadConfig::default());
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("echo")],
|
||||
vec![Ok(ActionResult {
|
||||
@@ -448,7 +694,12 @@ mod tests {
|
||||
/// but engine must never lose it).
|
||||
#[tokio::test]
|
||||
async fn mistral_format_call_id_preserved() {
|
||||
let thread = Thread::new("test", ThreadType::Foreground, ProjectId::new(), ThreadConfig::default());
|
||||
let thread = Thread::new(
|
||||
"test",
|
||||
ThreadType::Foreground,
|
||||
ProjectId::new(),
|
||||
ThreadConfig::default(),
|
||||
);
|
||||
let effects: Arc<dyn EffectExecutor> = Arc::new(MockEffects::new(
|
||||
vec![test_action("web_search")],
|
||||
vec![Ok(ActionResult {
|
||||
|
||||
@@ -481,6 +481,7 @@ mod tests {
|
||||
action_name: "web_search".into(),
|
||||
call_id: "call_123".into(),
|
||||
error: "No lease for action 'web_search'".into(),
|
||||
params_summary: None,
|
||||
},
|
||||
));
|
||||
|
||||
@@ -546,13 +547,19 @@ mod tests {
|
||||
thread.add_message(ThreadMessage::assistant("parallel calls"));
|
||||
thread.add_message(ThreadMessage::action_result("", "tool_a", "result_a"));
|
||||
thread.add_message(ThreadMessage::action_result("", "tool_b", "result_b"));
|
||||
thread.add_message(ThreadMessage::action_result("call_ok", "tool_c", "result_c"));
|
||||
thread.add_message(ThreadMessage::action_result(
|
||||
"call_ok", "tool_c", "result_c",
|
||||
));
|
||||
|
||||
let issues = analyze_trace(&thread);
|
||||
let empty_issues: Vec<_> = issues
|
||||
.iter()
|
||||
.filter(|i| i.category == "empty_call_id")
|
||||
.collect();
|
||||
assert_eq!(empty_issues.len(), 2, "should flag exactly the 2 empty call_ids");
|
||||
assert_eq!(
|
||||
empty_issues.len(),
|
||||
2,
|
||||
"should flag exactly the 2 empty call_ids"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ pub use capability::registry::CapabilityRegistry;
|
||||
|
||||
// ── Re-exports: runtime ───────────────────────────────────────
|
||||
|
||||
pub use executor::prompt::PlatformInfo;
|
||||
pub use runtime::conversation::ConversationManager;
|
||||
pub use runtime::manager::ThreadManager;
|
||||
pub use runtime::messaging::ThreadOutcome;
|
||||
|
||||
@@ -116,12 +116,12 @@ fn keyword_match_score(doc: &MemoryDoc, keywords: &[String]) -> f64 {
|
||||
/// Priority weight by doc type. Higher = more useful for context injection.
|
||||
fn doc_type_weight(doc_type: DocType) -> f64 {
|
||||
match doc_type {
|
||||
DocType::Spec => 0.5, // Missing capability info is highest priority
|
||||
DocType::Skill => 0.45, // Skills with activation metadata and code snippets
|
||||
DocType::Lesson => 0.4, // Lessons prevent repeating mistakes
|
||||
DocType::Issue => 0.2, // Known problems
|
||||
DocType::Summary => 0.1, // Background context
|
||||
DocType::Note => 0.05, // Scratch notes, lowest priority
|
||||
DocType::Spec => 0.5, // Missing capability info is highest priority
|
||||
DocType::Skill => 0.45, // Skills with activation metadata and code snippets
|
||||
DocType::Lesson => 0.4, // Lessons prevent repeating mistakes
|
||||
DocType::Issue => 0.2, // Known problems
|
||||
DocType::Summary => 0.1, // Background context
|
||||
DocType::Note => 0.05, // Scratch notes, lowest priority
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +249,18 @@ impl ConversationManager {
|
||||
));
|
||||
// Thread stays active — waiting for approval
|
||||
}
|
||||
ThreadOutcome::NeedAuthentication {
|
||||
credential_name,
|
||||
action_name: _,
|
||||
call_id: _,
|
||||
parameters: _,
|
||||
} => {
|
||||
conv.add_entry(ConversationEntry::system_for_thread(
|
||||
thread_id,
|
||||
format!("Authentication required for credential: {credential_name}"),
|
||||
));
|
||||
// Thread stays active — waiting for OAuth completion
|
||||
}
|
||||
}
|
||||
self.store.save_conversation(conv).await?;
|
||||
}
|
||||
|
||||
@@ -261,10 +261,9 @@ impl ThreadManager {
|
||||
|
||||
// Transition Completed → Done
|
||||
if exec.thread.state == crate::types::thread::ThreadState::Completed
|
||||
&& let Err(e) = exec.thread.transition_to(
|
||||
crate::types::thread::ThreadState::Done,
|
||||
None,
|
||||
)
|
||||
&& let Err(e) = exec
|
||||
.thread
|
||||
.transition_to(crate::types::thread::ThreadState::Done, None)
|
||||
{
|
||||
tracing::warn!(thread_id = %thread_id, "failed to transition to Done: {e}");
|
||||
}
|
||||
|
||||
@@ -38,6 +38,14 @@ pub enum ThreadOutcome {
|
||||
call_id: String,
|
||||
parameters: serde_json::Value,
|
||||
},
|
||||
/// An action needs a credential that requires user authentication (e.g. OAuth).
|
||||
/// The thread pauses until the credential is available, then resumes.
|
||||
NeedAuthentication {
|
||||
credential_name: String,
|
||||
action_name: String,
|
||||
call_id: String,
|
||||
parameters: serde_json::Value,
|
||||
},
|
||||
}
|
||||
|
||||
/// A mailbox for sending signals to a running thread.
|
||||
|
||||
@@ -387,9 +387,10 @@ impl MissionManager {
|
||||
.count();
|
||||
|
||||
if thread.state == crate::types::thread::ThreadState::Done
|
||||
&& trace.issues.iter().all(|i| {
|
||||
i.severity != crate::executor::trace::IssueSeverity::Error
|
||||
})
|
||||
&& trace
|
||||
.issues
|
||||
.iter()
|
||||
.all(|i| i.severity != crate::executor::trace::IssueSeverity::Error)
|
||||
&& thread.step_count >= SKILL_EXTRACTION_MIN_STEPS
|
||||
&& action_count >= SKILL_EXTRACTION_MIN_ACTIONS
|
||||
{
|
||||
@@ -434,37 +435,28 @@ impl MissionManager {
|
||||
// ── Trigger 3: Conversation insights ────────────
|
||||
// Use the thread's project_id as a proxy for conversation scope.
|
||||
let conv_key = thread.project_id.0.to_string();
|
||||
let count = conv_thread_counts
|
||||
.entry(conv_key.clone())
|
||||
.or_insert(0);
|
||||
let count = conv_thread_counts.entry(conv_key.clone()).or_insert(0);
|
||||
*count += 1;
|
||||
|
||||
if (*count).is_multiple_of(CONVERSATION_INSIGHTS_INTERVAL) {
|
||||
// Collect recent thread goals for context
|
||||
let thread_goals: Vec<String> = match mgr
|
||||
.store
|
||||
.list_threads(thread.project_id)
|
||||
.await
|
||||
{
|
||||
Ok(threads) => threads
|
||||
.iter()
|
||||
.rev()
|
||||
.take(CONVERSATION_INSIGHTS_INTERVAL as usize)
|
||||
.map(|t| t.goal.clone())
|
||||
.collect(),
|
||||
Err(_) => vec![thread.goal.clone()],
|
||||
};
|
||||
let thread_goals: Vec<String> =
|
||||
match mgr.store.list_threads(thread.project_id).await {
|
||||
Ok(threads) => threads
|
||||
.iter()
|
||||
.rev()
|
||||
.take(CONVERSATION_INSIGHTS_INTERVAL as usize)
|
||||
.map(|t| t.goal.clone())
|
||||
.collect(),
|
||||
Err(_) => vec![thread.goal.clone()],
|
||||
};
|
||||
|
||||
// Collect sample user messages from recent threads
|
||||
let sample_messages: Vec<String> = thread
|
||||
.messages
|
||||
.iter()
|
||||
.filter(|m| {
|
||||
m.role == crate::types::message::MessageRole::User
|
||||
})
|
||||
.map(|m| {
|
||||
m.content.chars().take(200).collect::<String>()
|
||||
})
|
||||
.filter(|m| m.role == crate::types::message::MessageRole::User)
|
||||
.map(|m| m.content.chars().take(200).collect::<String>())
|
||||
.take(10)
|
||||
.collect();
|
||||
|
||||
@@ -567,10 +559,7 @@ impl MissionManager {
|
||||
/// Creates (if missing) the self-improvement, skill extraction, and
|
||||
/// conversation insights missions. This is the preferred entry point —
|
||||
/// call once at project bootstrap.
|
||||
pub async fn ensure_learning_missions(
|
||||
&self,
|
||||
project_id: ProjectId,
|
||||
) -> Result<(), EngineError> {
|
||||
pub async fn ensure_learning_missions(&self, project_id: ProjectId) -> Result<(), EngineError> {
|
||||
// 1. Error diagnosis (self-improvement) — existing
|
||||
self.ensure_self_improvement_mission(project_id).await?;
|
||||
|
||||
@@ -604,6 +593,21 @@ impl MissionManager {
|
||||
)
|
||||
.await?;
|
||||
|
||||
// 4. Expected behavior (user feedback loop)
|
||||
self.ensure_mission_by_metadata(
|
||||
project_id,
|
||||
"expected_behavior",
|
||||
"expected-behavior",
|
||||
EXPECTED_BEHAVIOR_GOAL,
|
||||
MissionCadence::OnSystemEvent {
|
||||
source: "user_feedback".into(),
|
||||
event_type: "expected_behavior".into(),
|
||||
},
|
||||
"Investigate user-reported expectation gaps and apply fixes",
|
||||
5, // max 5/day
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1013,85 +1017,7 @@ fn extract_json_from_response(response: &str) -> Option<serde_json::Value> {
|
||||
/// This is the "program.md" — a concrete, step-by-step prompt that tells the
|
||||
/// agent exactly what to do. Inspired by karpathy/autoresearch: the entire
|
||||
/// research org is a markdown file with an explicit loop.
|
||||
const SELF_IMPROVEMENT_GOAL: &str = "\
|
||||
You are a self-improvement agent for the IronClaw engine. You receive trigger \
|
||||
payloads containing execution trace issues from completed threads. Your job is \
|
||||
to diagnose root causes and apply fixes so the same issue doesn't recur.
|
||||
|
||||
## What you have access to
|
||||
|
||||
- `state[\"trigger_payload\"]` — JSON with `issues` (list of {severity, category, description, step}), \
|
||||
`error_messages` (actual error text from failed actions), `goal` (what the thread was trying to do), \
|
||||
and `source_thread_id`.
|
||||
- All tools: shell, read_file, write_file, apply_patch, web_search, memory_write, etc.
|
||||
- The codebase at the current working directory.
|
||||
- The fix pattern database in prior knowledge (if loaded).
|
||||
|
||||
## The experiment loop
|
||||
|
||||
For each issue in the trigger payload:
|
||||
|
||||
1. **Diagnose**: Read the error messages and issue descriptions. Classify the root cause:
|
||||
- PROMPT: The LLM made a mistake because the system prompt is missing a rule \
|
||||
(wrong tool name, bad API usage, ignoring tool results)
|
||||
- CONFIG: A default value is wrong (truncation length, iteration limit, timeout)
|
||||
- CODE: There is a bug in the engine or bridge code (crash, type error, missing conversion)
|
||||
|
||||
2. **Check the fix pattern database** in prior knowledge. Has this pattern been seen before? \
|
||||
If yes, apply the known strategy. If no, proceed to step 3.
|
||||
|
||||
3. **Apply the fix** based on the level:
|
||||
|
||||
Level 1 (PROMPT — low risk, apply directly):
|
||||
- Read the current prompt overlay: `memory_search(\"prompt:codeact_preamble\")`
|
||||
- Write an updated overlay with a new rule appended
|
||||
- Use `memory_write` with title=\"prompt:codeact_preamble\" and tags=[\"prompt_overlay\"]
|
||||
- The rule should be specific and actionable (e.g. \"Never call web_fetch — use http() instead\")
|
||||
|
||||
Level 2 (CONFIG — medium risk):
|
||||
- Use `read_file` to find the relevant constant or default
|
||||
- Use `shell` to create a git branch: `git checkout -b self-improve/issue-description`
|
||||
- Apply the change with `apply_patch` or `write_file`
|
||||
- Run tests: `cargo test -p ironclaw_engine`
|
||||
- If tests pass, commit. If not, revert: `git checkout main`
|
||||
|
||||
Level 3 (CODE — high risk, just propose):
|
||||
- Read the relevant source files
|
||||
- Describe the fix needed but DO NOT apply it directly
|
||||
- Log it as a recommendation in your FINAL() response
|
||||
|
||||
4. **Record what you did** — include in your FINAL() response:
|
||||
- What issue you analyzed
|
||||
- What level fix you applied (1/2/3)
|
||||
- What specific change you made
|
||||
- Next focus: what to look for next time
|
||||
|
||||
## Important rules
|
||||
|
||||
- Be specific. \"Never call web_fetch\" is good. \"Be careful with tool names\" is useless.
|
||||
- One fix per issue. Don't try to fix everything at once.
|
||||
- For Level 1 fixes, the rule must be one sentence that can be appended to the prompt.
|
||||
- If the trigger payload has no actionable issues (only Info severity), skip and call FINAL() immediately.
|
||||
- NEVER modify test files to make a fix pass.
|
||||
- NEVER modify security-sensitive code (safety layer, policy engine, leak detection).
|
||||
- If you can't diagnose the root cause after reading the errors, log it and move on.
|
||||
|
||||
## Level 1.5: Orchestrator patches (medium risk, auto-rollback)
|
||||
|
||||
The execution loop itself is Python code that you can modify. This is the \
|
||||
orchestrator — it handles tool dispatch, output formatting, state management, \
|
||||
and context building. If the bug is in the glue between the LLM and tools \
|
||||
(wrong output format, bad truncation, missing state), you can patch it directly.
|
||||
|
||||
To modify the orchestrator:
|
||||
1. Read current version: `memory_search(\"orchestrator:main\")`
|
||||
2. Make your change (keep it minimal — one fix at a time)
|
||||
3. Save the new version: `memory_write` with title=\"orchestrator:main\", \
|
||||
tags=[\"orchestrator_code\"], metadata={\"version\": N+1, \"parent_version\": N}
|
||||
4. The next thread will use your updated orchestrator
|
||||
|
||||
If your change causes 3 consecutive failures, the system auto-rolls back to \
|
||||
the previous version. So be conservative — test your logic mentally before saving.";
|
||||
const SELF_IMPROVEMENT_GOAL: &str = include_str!("../../prompts/mission_self_improvement.md");
|
||||
|
||||
/// Well-known title for the fix pattern database.
|
||||
pub const FIX_PATTERN_DB_TITLE: &str = "fix_pattern_database";
|
||||
@@ -1100,124 +1026,14 @@ pub const FIX_PATTERN_DB_TITLE: &str = "fix_pattern_database";
|
||||
pub const FIX_PATTERN_DB_TAG: &str = "fix_patterns";
|
||||
|
||||
/// The goal for the skill extraction mission.
|
||||
const SKILL_EXTRACTION_GOAL: &str = "\
|
||||
You extract reusable skills from successfully completed multi-step threads.
|
||||
|
||||
## Input
|
||||
|
||||
`state[\"trigger_payload\"]` contains:
|
||||
- `source_thread_id` — the thread that completed successfully
|
||||
- `goal` — what the thread accomplished
|
||||
- `step_count` — number of execution steps
|
||||
- `action_count` — number of tool actions executed
|
||||
- `actions_used` — list of tool names used
|
||||
- `total_tokens` — tokens consumed
|
||||
|
||||
## Output Format
|
||||
|
||||
Save as a Skill memory doc via `memory_write(target=\"memory\", content=skill_prompt)` with:
|
||||
- title: `\"skill:<short-name>\"` (e.g., \"skill:github-issue-triage\")
|
||||
- doc_type: `\"skill\"`
|
||||
- metadata JSON:
|
||||
```json
|
||||
{
|
||||
\"name\": \"<short-name>\",
|
||||
\"version\": 1,
|
||||
\"description\": \"<one-line description>\",
|
||||
\"activation\": {
|
||||
\"keywords\": [\"<keyword1>\", \"<keyword2>\"],
|
||||
\"patterns\": [\"<optional regex>\"],
|
||||
\"tags\": [\"<domain-tag>\"],
|
||||
\"exclude_keywords\": [],
|
||||
\"max_context_tokens\": <estimated budget, e.g. 1000>
|
||||
},
|
||||
\"source\": \"extracted\",
|
||||
\"trust\": \"trusted\",
|
||||
\"code_snippets\": [
|
||||
{
|
||||
\"name\": \"<function_name>\",
|
||||
\"code\": \"def <function_name>(...):\\n ...\",
|
||||
\"description\": \"<what it does>\"
|
||||
}
|
||||
],
|
||||
\"metrics\": {\"usage_count\": 0, \"success_count\": 0, \"failure_count\": 0},
|
||||
\"content_hash\": \"\"
|
||||
}
|
||||
```
|
||||
|
||||
## Process
|
||||
|
||||
1. Search for the source thread's context: `memory_search(query=goal)`
|
||||
2. Check for existing skills: `memory_search(query=\"skill:\")`
|
||||
3. If a similar skill exists, update it (increment version) rather than creating a duplicate
|
||||
4. Extract:
|
||||
- Activation keywords from the goal + user messages (be specific, not generic)
|
||||
- Step-by-step instructions as the prompt content
|
||||
- Python code snippets for CodeAct (reusable functions using exact tool names)
|
||||
- Domain tags (e.g., \"github\", \"api\", \"data\")
|
||||
|
||||
## Output (FINAL)
|
||||
|
||||
Report what you did:
|
||||
- The skill title and a one-line summary
|
||||
- Whether it is new or an update to an existing skill
|
||||
- Next focus: what patterns to watch for
|
||||
|
||||
## Rules
|
||||
|
||||
- Only extract skills from threads with 3+ distinct tool calls
|
||||
- Keywords must be specific (not generic words like \"help\", \"do\", \"make\")
|
||||
- Code snippets must use exact tool function names as they appear in the thread
|
||||
- If the thread was a trivial query-response, call FINAL(\"No skill needed — simple interaction\") \
|
||||
and stop immediately
|
||||
- One skill per FINAL — do not combine unrelated procedures
|
||||
";
|
||||
const SKILL_EXTRACTION_GOAL: &str = include_str!("../../prompts/mission_skill_extraction.md");
|
||||
|
||||
/// The goal for the conversation insights mission.
|
||||
const CONVERSATION_INSIGHTS_GOAL: &str = "\
|
||||
You extract user preferences, patterns, and domain knowledge from a batch of recent \
|
||||
conversation threads.
|
||||
const CONVERSATION_INSIGHTS_GOAL: &str =
|
||||
include_str!("../../prompts/mission_conversation_insights.md");
|
||||
|
||||
## Input
|
||||
|
||||
`state[\"trigger_payload\"]` contains:
|
||||
- `project_id` — the project scope
|
||||
- `completed_thread_count` — total threads completed in this conversation
|
||||
- `thread_goals` — list of recent thread goals (what the user asked for)
|
||||
- `sample_user_messages` — sample of actual user messages (truncated to 200 chars)
|
||||
|
||||
## Process
|
||||
|
||||
1. Analyze the thread goals and user messages for patterns
|
||||
2. Search existing insights: `memory_search(query=\"user preferences\")` and \
|
||||
`memory_search(query=\"domain knowledge\")`
|
||||
3. Extract NEW insights not already recorded in memory
|
||||
4. Write each insight to memory via `memory_write(target=\"memory\", content=insight_text)` \
|
||||
with title format \"insight:<category>:<topic>\"
|
||||
|
||||
## Categories to look for
|
||||
|
||||
- **Preferences**: communication style, format choices, tool preferences
|
||||
- **Domain**: project names, API patterns, data formats, technology stack
|
||||
- **Workflow**: recurring task sequences, common follow-up questions
|
||||
- **Corrections**: things the user corrected or repeated — these signal unmet expectations
|
||||
|
||||
## Output (FINAL)
|
||||
|
||||
Report:
|
||||
- Number of new insights extracted (0 is fine)
|
||||
- Brief list of what was found
|
||||
- Next focus
|
||||
|
||||
## Rules
|
||||
|
||||
- Only record actionable, specific insights — not vague observations
|
||||
- Do not record personal information, only work patterns
|
||||
- If no meaningful new insights after analysis, call FINAL(\"No new insights — \
|
||||
conversation patterns already captured\") immediately
|
||||
- Merge with existing insight docs rather than creating duplicates
|
||||
- Max 5 insights per run to keep quality high
|
||||
";
|
||||
/// The goal for the expected-behavior mission (user feedback loop).
|
||||
const EXPECTED_BEHAVIOR_GOAL: &str = include_str!("../../prompts/mission_expected_behavior.md");
|
||||
|
||||
/// Seed content for the fix pattern database.
|
||||
const SEED_FIX_PATTERNS: &str = "\
|
||||
|
||||
@@ -58,6 +58,14 @@ pub enum EngineError {
|
||||
|
||||
#[error("skill error: {reason}")]
|
||||
Skill { reason: String },
|
||||
|
||||
#[error("authentication required for credential '{credential_name}'")]
|
||||
NeedAuthentication {
|
||||
credential_name: String,
|
||||
action_name: String,
|
||||
call_id: String,
|
||||
parameters: serde_json::Value,
|
||||
},
|
||||
}
|
||||
|
||||
use crate::types::project::ProjectId;
|
||||
|
||||
@@ -8,6 +8,71 @@ use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::types::capability::LeaseId;
|
||||
|
||||
/// Generate a short human-readable summary of tool parameters for display.
|
||||
///
|
||||
/// For `http`: shows the URL. For `web_search`: shows the query.
|
||||
/// For other tools: shows the first string argument, truncated.
|
||||
/// Returns `None` for empty or unrecognizable params.
|
||||
pub fn summarize_params(action_name: &str, params: &serde_json::Value) -> Option<String> {
|
||||
let summary = match action_name {
|
||||
"http" | "web_fetch" => params.get("url").and_then(|v| v.as_str()).map(|u| {
|
||||
if u.len() > 80 {
|
||||
format!("{}...", &u[..77])
|
||||
} else {
|
||||
u.to_string()
|
||||
}
|
||||
}),
|
||||
"web_search" | "llm_context" => params
|
||||
.get("query")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|q| truncate(q, 60)),
|
||||
"memory_search" => params
|
||||
.get("query")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|q| truncate(q, 60)),
|
||||
"memory_write" => params
|
||||
.get("target")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|t| t.to_string()),
|
||||
"memory_read" => params
|
||||
.get("path")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|p| p.to_string()),
|
||||
"shell" => params
|
||||
.get("command")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|c| truncate(c, 60)),
|
||||
"message" => params
|
||||
.get("content")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|c| truncate(c, 40)),
|
||||
_ => {
|
||||
// Generic: show first string value
|
||||
if let Some(obj) = params.as_object() {
|
||||
obj.values()
|
||||
.find_map(|v| v.as_str())
|
||||
.map(|s| truncate(s, 50))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
summary.filter(|s| !s.is_empty())
|
||||
}
|
||||
|
||||
fn truncate(s: &str, max: usize) -> String {
|
||||
if s.len() <= max {
|
||||
s.to_string()
|
||||
} else {
|
||||
// Find a safe UTF-8 boundary
|
||||
let mut end = max.min(s.len());
|
||||
while end > 0 && !s.is_char_boundary(end) {
|
||||
end -= 1;
|
||||
}
|
||||
format!("{}...", &s[..end])
|
||||
}
|
||||
}
|
||||
use crate::types::step::{StepId, TokenUsage};
|
||||
use crate::types::thread::{ThreadId, ThreadState};
|
||||
|
||||
@@ -76,12 +141,18 @@ pub enum EventKind {
|
||||
action_name: String,
|
||||
call_id: String,
|
||||
duration_ms: u64,
|
||||
/// Short human-readable summary of parameters (e.g., URL for http tool).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
params_summary: Option<String>,
|
||||
},
|
||||
ActionFailed {
|
||||
step_id: StepId,
|
||||
action_name: String,
|
||||
call_id: String,
|
||||
error: String,
|
||||
/// Short human-readable summary of parameters.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
params_summary: Option<String>,
|
||||
},
|
||||
|
||||
// ── Capability leases ───────────────────────────────────
|
||||
@@ -132,6 +203,11 @@ pub enum EventKind {
|
||||
error: String,
|
||||
},
|
||||
|
||||
// ── Skill activation ───────────────────────────────────────
|
||||
SkillActivated {
|
||||
skill_names: Vec<String>,
|
||||
},
|
||||
|
||||
// ── Orchestrator versioning ───────────────────────────────
|
||||
OrchestratorRollback {
|
||||
from_version: u64,
|
||||
|
||||
@@ -50,20 +50,20 @@ pub mod registry;
|
||||
|
||||
// Re-export core types at crate root for convenience.
|
||||
pub use types::{
|
||||
ActivationCriteria, GatingRequirements, LoadedSkill, OpenClawMeta, ProviderRefreshStrategy,
|
||||
SkillCredentialLocation, SkillCredentialSpec, SkillManifest, SkillMetadata, SkillOAuthConfig,
|
||||
SkillSource, SkillTrust, MAX_PROMPT_FILE_SIZE,
|
||||
ActivationCriteria, GatingRequirements, LoadedSkill, MAX_PROMPT_FILE_SIZE, OpenClawMeta,
|
||||
ProviderRefreshStrategy, SkillCredentialLocation, SkillCredentialSpec, SkillManifest,
|
||||
SkillMetadata, SkillOAuthConfig, SkillSource, SkillTrust,
|
||||
};
|
||||
|
||||
pub use gating::{GatingResult, check_requirements, check_requirements_sync};
|
||||
pub use parser::{ParsedSkill, SkillParseError, parse_skill_md};
|
||||
pub use selector::{prefilter_skills, MAX_SKILL_CONTEXT_TOKENS};
|
||||
pub use selector::{MAX_SKILL_CONTEXT_TOKENS, prefilter_skills};
|
||||
pub use validation::{
|
||||
escape_skill_content, escape_xml_attr, normalize_line_endings, validate_credential_name,
|
||||
validate_credential_spec, validate_skill_name,
|
||||
};
|
||||
pub use gating::{GatingResult, check_requirements, check_requirements_sync};
|
||||
|
||||
#[cfg(feature = "registry")]
|
||||
pub use registry::{SkillRegistry, SkillRegistryError, compute_hash};
|
||||
#[cfg(feature = "catalog")]
|
||||
pub use catalog::{CatalogEntry, CatalogSearchOutcome, SkillCatalog, shared_catalog};
|
||||
#[cfg(feature = "registry")]
|
||||
pub use registry::{SkillRegistry, SkillRegistryError, compute_hash};
|
||||
|
||||
@@ -290,15 +290,18 @@ impl LoadedSkill {
|
||||
|
||||
patterns
|
||||
.iter()
|
||||
.filter_map(
|
||||
|p| match regex::RegexBuilder::new(p).size_limit(MAX_REGEX_SIZE).build() {
|
||||
.filter_map(|p| {
|
||||
match regex::RegexBuilder::new(p)
|
||||
.size_limit(MAX_REGEX_SIZE)
|
||||
.build()
|
||||
{
|
||||
Ok(re) => Some(re),
|
||||
Err(e) => {
|
||||
tracing::warn!("Invalid activation regex pattern '{}': {}", p, e);
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,42 @@ Users reported `"No lease for action 'routine_create'"` when asking the engine t
|
||||
|
||||
**Fix**: Registered `mission_create`, `mission_list`, `mission_fire`, `mission_pause`, `mission_resume`, `mission_delete` as a `"missions"` capability in `router.rs`. Descriptions mention "routine" so the LLM maps user intent correctly. Removed all `routine_*` aliases from the effect adapter — `routine_*` names added to `is_v1_only_tool()` blocklist with clear error directing to `mission_*`.
|
||||
|
||||
## Session 9: Trace Pipeline Fix, Monty Builtins, Self-Awareness (2026-03-28)
|
||||
|
||||
Three fixes driven by analyzing a live engine trace (`engine_trace_20260328T030519.json`) from the hourly Iran-region monitor mission.
|
||||
|
||||
### Event Pipeline Loss in CodeAct
|
||||
|
||||
**The bug**: The `no_tools_used` trace issue fired as a false positive — the mission thread called `web_search` 5 times, `llm_context` once, and `llm_query` once, yet the trace had zero `ActionExecuted` events.
|
||||
|
||||
**Root cause**: `handle_execute_code_step()` in `orchestrator.rs` received `CodeExecutionResult::events` (populated by `dispatch_action()` in `scripting.rs`) but never transferred them to `thread.events` or broadcast them via `event_tx`. The function took `&Thread` (immutable) and had no access to the event broadcast channel. Compare with `handle_execute_action()` which correctly calls `emit_and_record()` for each action.
|
||||
|
||||
**Fix**: Changed `handle_execute_code_step()` to take `&mut Thread` + `event_tx`, iterate over `result.events`, push each to `thread.events` and broadcast via `event_tx` — same pattern as `handle_execute_action()`. The `no_tools_used` detector in `trace.rs` now works correctly for CodeAct because `ActionExecuted` events are present.
|
||||
|
||||
### globals() NameError in Monty
|
||||
|
||||
**The bug**: LLM-generated code used `"mission_create" in globals()` to probe available capabilities before calling them. Monty doesn't implement `globals()` as a builtin, so NameLookup returned `Undefined` → NameError → code execution failure.
|
||||
|
||||
**Fix**: Added `globals`/`locals` to the NameLookup handler as callable function stubs, and a FunctionCall handler that returns a `Dict` of all known action names (from capability leases) as keys. Code like `"tool_name" in globals()` now works for capability probing.
|
||||
|
||||
### Platform Self-Awareness
|
||||
|
||||
**The problem**: The agent had no knowledge of its own identity. It didn't know it was IronClaw, its GitHub repo, its version, active channels, LLM backend, or database. The system prompt just said "You are IronClaw Agent, a secure autonomous assistant" with no specifics.
|
||||
|
||||
**The insight**: Identity infrastructure was 85% built — `IDENTITY.md`, `SOUL.md`, `USER.md`, `AGENTS.md` injection worked for *user* identity. But nothing existed for *platform* identity. This isn't workspace-level (it changes with runtime config), so a seed file was wrong — it needed to be injected dynamically.
|
||||
|
||||
**Implementation** (8 files):
|
||||
|
||||
1. **`PlatformInfo` struct** (`executor/prompt.rs`) — version, llm_backend, model_name, database_backend, active_channels, owner_id, repo_url. `to_prompt_section()` renders a `## Platform` block.
|
||||
|
||||
2. **CodeAct path** — `build_codeact_system_prompt()` accepts optional `PlatformInfo`, injects before tool listing.
|
||||
|
||||
3. **Tier 0 path** — `Reasoning` struct gets `with_platform_info()` builder, `build_runtime_section()` prepends the platform block.
|
||||
|
||||
4. **Runtime wiring** — `Agent::platform_info()` constructs from `AgentDeps` (version from `CARGO_PKG_VERSION`, backend/model/owner from deps, channels from `ChannelManager`).
|
||||
|
||||
**Test coverage**: 2 new tests (platform info injection + absence). 195 engine tests pass, zero clippy warnings.
|
||||
|
||||
## Architecture Evolution
|
||||
|
||||
```
|
||||
@@ -171,6 +207,8 @@ Session 7: Integration scaling: Capabilities as knowledge → http action
|
||||
(not Pica-style per-action tools — tool list bloat kills LLM accuracy)
|
||||
Session 8: Skills-based OAuth (credential specs in YAML frontmatter)
|
||||
+ HTTP tool zero-leak hardening + mission capability leases
|
||||
Session 9: CodeAct event pipeline fix (ActionExecuted events were lost)
|
||||
+ Monty globals() builtin + platform self-awareness injection
|
||||
```
|
||||
|
||||
## Key Commits
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
name: 1-password
|
||||
version: "1.0.0"
|
||||
description: 1Password API — 1Password is a secure password manager that consolidates credentials
|
||||
activation:
|
||||
keywords:
|
||||
- "1-password"
|
||||
- "1password"
|
||||
- "security"
|
||||
patterns:
|
||||
- "(?i)1.?password"
|
||||
tags:
|
||||
- "security"
|
||||
- "identity"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [1PASSWORD_CONNECT_SERVER_URL, 1PASSWORD_CONNECT_ACCESS_TOKEN]
|
||||
---
|
||||
|
||||
# 1Password API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`{1PASSWORD_CONNECT_SERVER_URL}/v1`
|
||||
|
||||
## Actions
|
||||
|
||||
**List vaults:**
|
||||
```
|
||||
http(method="GET", url="{1PASSWORD_CONNECT_SERVER_URL}/v1/vaults")
|
||||
```
|
||||
|
||||
**List items in vault:**
|
||||
```
|
||||
http(method="GET", url="{1PASSWORD_CONNECT_SERVER_URL}/v1/vaults/{vault_id}/items")
|
||||
```
|
||||
|
||||
**Get item details:**
|
||||
```
|
||||
http(method="GET", url="{1PASSWORD_CONNECT_SERVER_URL}/v1/vaults/{vault_id}/items/{item_id}")
|
||||
```
|
||||
|
||||
**Create item:**
|
||||
```
|
||||
http(method="POST", url="{1PASSWORD_CONNECT_SERVER_URL}/v1/vaults/{vault_id}/items", body={"vault": {"id": "<vault_id>"},"category": "LOGIN","title": "My Login","fields": [{"purpose": "USERNAME","value": "[email protected]"},{"purpose": "PASSWORD","value": "secret"}]})
|
||||
```
|
||||
|
||||
**Delete item:**
|
||||
```
|
||||
http(method="DELETE", url="{1PASSWORD_CONNECT_SERVER_URL}/v1/vaults/{vault_id}/items/{item_id}")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Item categories: `LOGIN`, `PASSWORD`, `SECURE_NOTE`, `CREDIT_CARD`, `IDENTITY`, `DOCUMENT`.
|
||||
- Fields have `purpose`: `USERNAME`, `PASSWORD`, `NOTES`.
|
||||
- The Connect server must be running and accessible at the configured URL.
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
name: 7-shifts
|
||||
version: "1.0.0"
|
||||
description: 7shifts API — 7Shifts is a cloud‑based workforce management platform tailored for restaurants
|
||||
activation:
|
||||
keywords:
|
||||
- "7-shifts"
|
||||
- "7shifts"
|
||||
- "hospitality"
|
||||
patterns:
|
||||
- "(?i)7.?shifts"
|
||||
tags:
|
||||
- "hospitality"
|
||||
- "scheduling"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# 7shifts API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> 7Shifts is a cloud‑based workforce management platform tailored for restaurants, combining intuitive drag‑and‑drop scheduling, mobile time tracking, automated payroll and tip management, labor complia
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **OAuth 2.0**. The token is managed automatically — no manual auth setup required in API calls.
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: ably-control
|
||||
version: "1.0.0"
|
||||
description: Ably Control API — Ably Control API is a RESTful interface that enables developers and DevOps teams
|
||||
activation:
|
||||
keywords:
|
||||
- "ably-control"
|
||||
- "ably control"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)ably.?control"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABLY_CONTROL_ACCESS_TOKEN]
|
||||
---
|
||||
|
||||
# Ably Control API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Ably Control API is a RESTful interface that enables developers and DevOps teams to programmatically provision, configure, and manage real-time infrastructure—such as apps, API keys, namespaces, queue
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **Bearer Token** authentication. The token is injected automatically into the `Authorization` header.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABLY_CONTROL_ACCESS_TOKEN` — Access Token
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: ably
|
||||
version: "1.0.0"
|
||||
description: Ably API — Ably Pub/Sub is a global serverless real-time messaging platform that delivers s
|
||||
activation:
|
||||
keywords:
|
||||
- "ably"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)ably"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABLY_ENCODED_API_KEY]
|
||||
---
|
||||
|
||||
# Ably API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `Authorization` header — **never construct auth headers manually**.
|
||||
|
||||
> Ably Pub/Sub is a global serverless real-time messaging platform that delivers sub‑60 ms latency pub/sub capabilities—including message history, presence detection, exactly‑once delivery, and guarante
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `Authorization` header.
|
||||
Format: `Authorization: Basic ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABLY_ENCODED_API_KEY` — API Key (RFC 4648 Base64 Encoded)
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: abstract-avatars
|
||||
version: "1.0.0"
|
||||
description: Abstract Avatars API — An API that generates customizable user avatars based on names or unique identif
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-avatars"
|
||||
- "abstract avatars"
|
||||
- "avatar generation"
|
||||
patterns:
|
||||
- "(?i)abstract.?avatars"
|
||||
tags:
|
||||
- "avatar"
|
||||
- "images"
|
||||
- "avatar-generation"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_AVATARS_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract Avatars API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that generates customizable user avatars based on names or unique identifiers, enabling applications to automatically create consistent, visually distinct profile images without requiring users
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_AVATARS_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abstract-company-enrichment
|
||||
version: "1.0.0"
|
||||
description: Abstract Company Enrichment API — An API that enriches company records with firmographic data such as industry
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-company-enrichment"
|
||||
- "abstract company enrichment"
|
||||
- "data enrichment"
|
||||
patterns:
|
||||
- "(?i)abstract.?company.?enrichment"
|
||||
tags:
|
||||
- "data-enrichment"
|
||||
- "enrichment"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_COMPANY_ENRICHMENT_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract Company Enrichment API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that enriches company records with firmographic data such as industry, size, location, and domain details, enabling businesses to enhance lead profiles, improve segmentation, and power more acc
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_COMPANY_ENRICHMENT_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abstract-email-reputation
|
||||
version: "1.0.0"
|
||||
description: Abstract Email Reputation API — An API that evaluates the reputation of email addresses by analyzing risk factor
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-email-reputation"
|
||||
- "abstract email reputation"
|
||||
- "email verification"
|
||||
patterns:
|
||||
- "(?i)abstract.?email.?reputation"
|
||||
tags:
|
||||
- "tools"
|
||||
- "email-verification"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_EMAIL_REPUTATION_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract Email Reputation API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that evaluates the reputation of email addresses by analyzing risk factors to help applications improve deliverability, reduce fraud, and enhance email validation accuracy.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_EMAIL_REPUTATION_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abstract-iban-validation
|
||||
version: "1.0.0"
|
||||
description: Abstract IBAN Validation API — An API that validates IBAN numbers by checking format, bank details
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-iban-validation"
|
||||
- "abstract iban validation"
|
||||
- "iban validation"
|
||||
patterns:
|
||||
- "(?i)abstract.?iban.?validation"
|
||||
tags:
|
||||
- "tools"
|
||||
- "iban-validation"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_IBAN_VALIDATION_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract IBAN Validation API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that validates IBAN numbers by checking format, bank details, and country-specific rules to help businesses prevent payment errors, reduce fraud risk, and streamline international transactions.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_IBAN_VALIDATION_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abstract-ip-intelligence
|
||||
version: "1.0.0"
|
||||
description: Abstract IP Intelligence API — An API that provides IP address data including geolocation, ISP
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-ip-intelligence"
|
||||
- "abstract ip intelligence"
|
||||
- "ip intelligence"
|
||||
patterns:
|
||||
- "(?i)abstract.?ip.?intelligence"
|
||||
tags:
|
||||
- "tools"
|
||||
- "ip-intelligence"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_IP_INTELLIGENCE_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract IP Intelligence API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that provides IP address data including geolocation, ISP, proxy and VPN detection, and risk signals to help applications enhance security, prevent fraud, and deliver location-aware experiences.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_IP_INTELLIGENCE_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abstract-phone-intelligence
|
||||
version: "1.0.0"
|
||||
description: Abstract Phone Intelligence API — An API that validates and enriches phone numbers with carrier, location
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-phone-intelligence"
|
||||
- "abstract phone intelligence"
|
||||
- "phone validation"
|
||||
patterns:
|
||||
- "(?i)abstract.?phone.?intelligence"
|
||||
tags:
|
||||
- "tools"
|
||||
- "phone-validation"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_PHONE_INTELLIGENCE_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract Phone Intelligence API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that validates and enriches phone numbers with carrier, location, and line type data, enabling applications to verify user input, detect fraud risk, and improve communication accuracy globally.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_PHONE_INTELLIGENCE_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abstract-public-holidays
|
||||
version: "1.0.0"
|
||||
description: Abstract Public Holidays API — An API that delivers official public holiday data by country and year
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-public-holidays"
|
||||
- "abstract public holidays"
|
||||
- "public holidays"
|
||||
patterns:
|
||||
- "(?i)abstract.?public.?holidays"
|
||||
tags:
|
||||
- "tools"
|
||||
- "public-holidays"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_PUBLIC_HOLIDAYS_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract Public Holidays API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that delivers official public holiday data by country and year, enabling applications to access national and regional holiday calendars for scheduling, localization, and compliance use cases.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_PUBLIC_HOLIDAYS_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abstract-vat-validation
|
||||
version: "1.0.0"
|
||||
description: Abstract Vat Validation API — An API that validates VAT numbers against official registries
|
||||
activation:
|
||||
keywords:
|
||||
- "abstract-vat-validation"
|
||||
- "abstract vat validation"
|
||||
- "vat validation"
|
||||
patterns:
|
||||
- "(?i)abstract.?vat.?validation"
|
||||
tags:
|
||||
- "tools"
|
||||
- "vat-validation"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABSTRACT_VAT_VALIDATION_API_KEY]
|
||||
---
|
||||
|
||||
# Abstract Vat Validation API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_key` query parameter.
|
||||
|
||||
> An API that validates VAT numbers against official registries, confirms company details, and helps businesses ensure tax compliance, reduce fraud risk, and automate cross-border invoicing workflows.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_key`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABSTRACT_VAT_VALIDATION_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: abyssale
|
||||
version: "1.0.0"
|
||||
description: Abyssale API — A cloud-based creative automation solution that helps teams design, generate
|
||||
activation:
|
||||
keywords:
|
||||
- "abyssale"
|
||||
- "creative automation platform"
|
||||
patterns:
|
||||
- "(?i)abyssale"
|
||||
tags:
|
||||
- "tools"
|
||||
- "creative-automation-platform"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ABYSSALE_API_KEY]
|
||||
---
|
||||
|
||||
# Abyssale API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `x-api-key` header — **never construct auth headers manually**.
|
||||
|
||||
> A cloud-based creative automation solution that helps teams design, generate, and scale thousands of on-brand visual assets in minutes from a single template, accelerates production through APIs and i
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `x-api-key` header.
|
||||
Format: `x-api-key: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ABYSSALE_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
name: activecampaign
|
||||
version: "1.0.0"
|
||||
description: ActiveCampaign API — contacts, deals, automations, campaigns, lists
|
||||
activation:
|
||||
keywords:
|
||||
- "activecampaign"
|
||||
- "active campaign"
|
||||
- "marketing automation"
|
||||
exclude_keywords:
|
||||
- "hubspot"
|
||||
- "mailchimp"
|
||||
patterns:
|
||||
- "(?i)active.?campaign.*(contact|deal|automation|campaign)"
|
||||
tags:
|
||||
- "marketing"
|
||||
- "crm"
|
||||
- "automation"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ACTIVECAMPAIGN_URL, ACTIVECAMPAIGN_API_KEY]
|
||||
---
|
||||
|
||||
# ActiveCampaign API v3
|
||||
|
||||
Use the `http` tool. Include `Api-Token` header.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://{ACTIVECAMPAIGN_URL}.api-us1.com/api/3`
|
||||
|
||||
## Actions
|
||||
|
||||
**List contacts:**
|
||||
```
|
||||
http(method="GET", url="https://{account}.api-us1.com/api/3/contacts?limit=20", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}])
|
||||
```
|
||||
|
||||
**Search contacts:**
|
||||
```
|
||||
http(method="GET", url="https://{account}.api-us1.com/api/3/[email protected]", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}])
|
||||
```
|
||||
|
||||
**Create contact:**
|
||||
```
|
||||
http(method="POST", url="https://{account}.api-us1.com/api/3/contacts", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}], body={"contact": {"email": "[email protected]", "firstName": "John", "lastName": "Doe", "phone": "+1234567890"}})
|
||||
```
|
||||
|
||||
**Update contact:**
|
||||
```
|
||||
http(method="PUT", url="https://{account}.api-us1.com/api/3/contacts/<contact_id>", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}], body={"contact": {"firstName": "Updated"}})
|
||||
```
|
||||
|
||||
**List deals:**
|
||||
```
|
||||
http(method="GET", url="https://{account}.api-us1.com/api/3/deals?limit=20", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}])
|
||||
```
|
||||
|
||||
**Create deal:**
|
||||
```
|
||||
http(method="POST", url="https://{account}.api-us1.com/api/3/deals", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}], body={"deal": {"title": "New Deal", "value": 5000, "currency": "usd", "contact": "<contact_id>", "group": "<pipeline_id>", "stage": "<stage_id>"}})
|
||||
```
|
||||
|
||||
**Add contact to automation:**
|
||||
```
|
||||
http(method="POST", url="https://{account}.api-us1.com/api/3/contactAutomations", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}], body={"contactAutomation": {"contact": "<contact_id>", "automation": "<automation_id>"}})
|
||||
```
|
||||
|
||||
**List automations:**
|
||||
```
|
||||
http(method="GET", url="https://{account}.api-us1.com/api/3/automations?limit=20", headers=[{"name": "Api-Token", "value": "{ACTIVECAMPAIGN_API_KEY}"}])
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- All request/response bodies wrap data in the resource name: `{"contact": {...}}`, `{"contacts": [...]}`.
|
||||
- Deal values are in cents (integer).
|
||||
- Pagination: `limit` + `offset`. Check `meta.total` for count.
|
||||
- Tags can be added via `/api/3/contactTags` with `{"contactTag": {"contact": "id", "tag": "id"}}`.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: affinity-co
|
||||
version: "1.0.0"
|
||||
description: Affinity.co API — Affinity is a relationship intelligence CRM that automatically captures and anal
|
||||
activation:
|
||||
keywords:
|
||||
- "affinity-co"
|
||||
- "affinity.co"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)affinity.?co"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [AFFINITY_CO_API_KEY]
|
||||
---
|
||||
|
||||
# Affinity.co API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
> Affinity is a relationship intelligence CRM that automatically captures and analyzes your team's communication data to surface valuable connections, streamline deal management, and help you close more
|
||||
|
||||
## Authentication
|
||||
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `AFFINITY_CO_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: agent-mail
|
||||
version: "1.0.0"
|
||||
description: AgentMail API — Agent Mail enables developers to give AI agents unique
|
||||
activation:
|
||||
keywords:
|
||||
- "agent-mail"
|
||||
- "agentmail"
|
||||
- "ai"
|
||||
patterns:
|
||||
- "(?i)agent.?mail"
|
||||
tags:
|
||||
- "ai"
|
||||
- "machine-learning"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [AGENT_MAIL_API_KEY]
|
||||
---
|
||||
|
||||
# AgentMail API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Agent Mail enables developers to give AI agents unique, programmable email inboxes that can send, receive, and act on emails at scale—featuring API-first integration, custom domains, and built-in deli
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **Bearer Token** authentication. The token is injected automatically into the `Authorization` header.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `AGENT_MAIL_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: agent-ql
|
||||
version: "1.0.0"
|
||||
description: AgentQL API — AgentQL is a natural language interface that allows users to query their data us
|
||||
activation:
|
||||
keywords:
|
||||
- "agent-ql"
|
||||
- "agentql"
|
||||
- "ai"
|
||||
patterns:
|
||||
- "(?i)agent.?ql"
|
||||
tags:
|
||||
- "ai"
|
||||
- "machine-learning"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [AGENTQL_API_KEY]
|
||||
---
|
||||
|
||||
# AgentQL API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `X-API-Key` header — **never construct auth headers manually**.
|
||||
|
||||
> AgentQL is a natural language interface that allows users to query their data using plain English, enabling seamless interaction with databases and APIs without writing traditional code.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `X-API-Key` header.
|
||||
Format: `X-API-Key: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `AGENTQL_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
name: agiled
|
||||
version: "1.0.0"
|
||||
description: Agiled API — Agiled is an all-in-one business management platform that helps freelancers and
|
||||
activation:
|
||||
keywords:
|
||||
- "agiled"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)agiled"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Agiled API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_token` query parameter.
|
||||
|
||||
> Agiled is an all-in-one business management platform that helps freelancers and small businesses manage CRM, projects, finances, contracts, invoicing and client portals within a unified workspace.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_token`.
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
name: ahrefs
|
||||
version: "1.0.0"
|
||||
description: Ahrefs API — Ahrefs is an all-in-one SEO toolset that helps businesses and marketers improve
|
||||
activation:
|
||||
keywords:
|
||||
- "ahrefs"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)ahrefs"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [AHREFS_API_KEY]
|
||||
---
|
||||
|
||||
# Ahrefs API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.ahrefs.com/v3`
|
||||
|
||||
## Actions
|
||||
|
||||
**Get domain rating:**
|
||||
```
|
||||
http(method="GET", url="https://api.ahrefs.com/v3/site-explorer/domain-rating?target=example.com&date=2026-03-01")
|
||||
```
|
||||
|
||||
**Get backlinks:**
|
||||
```
|
||||
http(method="GET", url="https://api.ahrefs.com/v3/site-explorer/all-backlinks?target=example.com&limit=10&mode=subdomains")
|
||||
```
|
||||
|
||||
**Get organic keywords:**
|
||||
```
|
||||
http(method="GET", url="https://api.ahrefs.com/v3/site-explorer/organic-keywords?target=example.com&limit=10&country=us")
|
||||
```
|
||||
|
||||
**Get referring domains:**
|
||||
```
|
||||
http(method="GET", url="https://api.ahrefs.com/v3/site-explorer/refdomains?target=example.com&limit=10&mode=subdomains")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- `target` can be a domain, subdomain, or URL.
|
||||
- `mode`: `exact`, `prefix`, `domain`, `subdomains`.
|
||||
- Dates in `YYYY-MM-DD` format.
|
||||
- Results are paginated with `offset` and `limit`.
|
||||
@@ -1,85 +0,0 @@
|
||||
---
|
||||
name: airtable
|
||||
version: "1.0.0"
|
||||
description: Airtable API — bases, tables, records, fields, views
|
||||
activation:
|
||||
keywords:
|
||||
- "airtable"
|
||||
- "airtable base"
|
||||
- "airtable record"
|
||||
exclude_keywords:
|
||||
- "google sheets"
|
||||
- "notion"
|
||||
patterns:
|
||||
- "(?i)airtable.*(base|table|record|field)"
|
||||
- "(?i)(create|list|update).*airtable"
|
||||
tags:
|
||||
- "database"
|
||||
- "spreadsheet"
|
||||
- "productivity"
|
||||
max_context_tokens: 1500
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [AIRTABLE_ACCESS_TOKEN]
|
||||
---
|
||||
|
||||
# Airtable Web API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected for `api.airtable.com`.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.airtable.com/v0`
|
||||
|
||||
## Actions
|
||||
|
||||
**List bases:**
|
||||
```
|
||||
http(method="GET", url="https://api.airtable.com/v0/meta/bases")
|
||||
```
|
||||
|
||||
**List tables in base:**
|
||||
```
|
||||
http(method="GET", url="https://api.airtable.com/v0/meta/bases/<base_id>/tables")
|
||||
```
|
||||
|
||||
**List records:**
|
||||
```
|
||||
http(method="GET", url="https://api.airtable.com/v0/<base_id>/<table_name>?maxRecords=20&view=Grid%20view")
|
||||
```
|
||||
|
||||
**List with filter:**
|
||||
```
|
||||
http(method="GET", url="https://api.airtable.com/v0/<base_id>/<table_name>?filterByFormula={Status}='Active'&sort[0][field]=Name&sort[0][direction]=asc&maxRecords=20")
|
||||
```
|
||||
|
||||
**Get record:**
|
||||
```
|
||||
http(method="GET", url="https://api.airtable.com/v0/<base_id>/<table_name>/<record_id>")
|
||||
```
|
||||
|
||||
**Create records:**
|
||||
```
|
||||
http(method="POST", url="https://api.airtable.com/v0/<base_id>/<table_name>", body={"records": [{"fields": {"Name": "Alice", "Email": "[email protected]", "Status": "Active"}}]})
|
||||
```
|
||||
|
||||
**Update records:**
|
||||
```
|
||||
http(method="PATCH", url="https://api.airtable.com/v0/<base_id>/<table_name>", body={"records": [{"id": "<record_id>", "fields": {"Status": "Done"}}]})
|
||||
```
|
||||
|
||||
**Delete records:**
|
||||
```
|
||||
http(method="DELETE", url="https://api.airtable.com/v0/<base_id>/<table_name>?records[]=<record_id1>&records[]=<record_id2>")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Base IDs start with `app`, table IDs with `tbl`, record IDs with `rec`.
|
||||
- Table name in URL must be URL-encoded if it contains spaces.
|
||||
- `filterByFormula` uses Airtable formula syntax: `{Field Name}='value'`, `AND(...)`, `OR(...)`.
|
||||
- Create/update accept up to 10 records per request.
|
||||
- Pagination: use `offset` from response. When absent, no more records.
|
||||
- Rate limit: 5 requests/second per base.
|
||||
- Field names are case-sensitive and must match exactly.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: alt-text-ai
|
||||
version: "1.0.0"
|
||||
description: AltText AI API — An AI-driven service that automatically analyzes images and generates descriptiv
|
||||
activation:
|
||||
keywords:
|
||||
- "alt-text-ai"
|
||||
- "alttext ai"
|
||||
- "generation tool"
|
||||
patterns:
|
||||
- "(?i)alt.?text.?ai"
|
||||
tags:
|
||||
- "tools"
|
||||
- "generation-tool"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ALT_TEXT_AI_API_KEY]
|
||||
---
|
||||
|
||||
# AltText AI API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `X-API-Key` header — **never construct auth headers manually**.
|
||||
|
||||
> An AI-driven service that automatically analyzes images and generates descriptive, SEO-friendly alt text to improve website accessibility, enhance search visibility across languages, and streamline im
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `X-API-Key` header.
|
||||
Format: `X-API-Key: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ALT_TEXT_AI_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,39 +0,0 @@
|
||||
---
|
||||
name: amazon-ads
|
||||
version: "1.0.0"
|
||||
description: Amazon Ads API — Amazon Ads is an advertising platform that enables brands to promote their produ
|
||||
activation:
|
||||
keywords:
|
||||
- "amazon-ads"
|
||||
- "amazon ads"
|
||||
- "marketing"
|
||||
patterns:
|
||||
- "(?i)amazon.?ads"
|
||||
tags:
|
||||
- "marketing"
|
||||
- "email"
|
||||
- "campaigns"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Amazon Ads API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Amazon Ads is an advertising platform that enables brands to promote their products across Amazon’s ecosystem, helping them reach shoppers through targeted ads, sponsored listings, and display campaig
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **OAuth 2.0**. The token is managed automatically — no manual auth setup required in API calls.
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: anchor-browser
|
||||
version: "1.0.0"
|
||||
description: Anchor Browser API — Anchor Browser is a cloud-hosted automation platform that lets AI agents interac
|
||||
activation:
|
||||
keywords:
|
||||
- "anchor-browser"
|
||||
- "anchor browser"
|
||||
- "web automation"
|
||||
patterns:
|
||||
- "(?i)anchor.?browser"
|
||||
tags:
|
||||
- "tools"
|
||||
- "web-automation"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ANCHOR_BROWSER_API_KEY]
|
||||
---
|
||||
|
||||
# Anchor Browser API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `anchor-api-key` header — **never construct auth headers manually**.
|
||||
|
||||
> Anchor Browser is a cloud-hosted automation platform that lets AI agents interact with web pages like a human—navigating sites, clicking, typing, submitting forms and extracting data—so teams can auto
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `anchor-api-key` header.
|
||||
Format: `anchor-api-key: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ANCHOR_BROWSER_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: anthropic-admin
|
||||
version: "1.0.0"
|
||||
description: Anthropic Admin API — Anthropic Admin provides administrative tools for managing access, API keys
|
||||
activation:
|
||||
keywords:
|
||||
- "anthropic-admin"
|
||||
- "anthropic admin"
|
||||
- "ai"
|
||||
patterns:
|
||||
- "(?i)anthropic.?admin"
|
||||
tags:
|
||||
- "ai"
|
||||
- "machine-learning"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ANTHROPIC_ADMIN_API_KEY]
|
||||
---
|
||||
|
||||
# Anthropic Admin API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `X-Api-Key` header — **never construct auth headers manually**.
|
||||
|
||||
> Anthropic Admin provides administrative tools for managing access, API keys, usage, billing, and organizational settings for applications built with Claude AI models, allowing teams to control permiss
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `X-Api-Key` header.
|
||||
Format: `X-Api-Key: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `ANTHROPIC_ADMIN_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
name: anthropic
|
||||
version: "1.0.0"
|
||||
description: Anthropic API — Anthropic is an AI safety and research company focused on building reliable
|
||||
activation:
|
||||
keywords:
|
||||
- "anthropic"
|
||||
- "ai"
|
||||
patterns:
|
||||
- "(?i)anthropic"
|
||||
tags:
|
||||
- "ai"
|
||||
- "machine-learning"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ANTHROPIC_API_KEY]
|
||||
---
|
||||
|
||||
# Anthropic API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `x-api-key` header — **never construct auth headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.anthropic.com/v1`
|
||||
|
||||
**Required headers**: `x-api-key: {ANTHROPIC_API_KEY}`, `anthropic-version: 2023-06-01`
|
||||
|
||||
## Actions
|
||||
|
||||
**Create message:**
|
||||
```
|
||||
http(method="POST", url="https://api.anthropic.com/v1/messages", headers=[{"name": "x-api-key","value": "{ANTHROPIC_API_KEY}"},{"name": "anthropic-version","value": "2023-06-01"}], body={"model": "claude-sonnet-4-20250514","max_tokens": 1024,"messages": [{"role": "user","content": "Hello"}]})
|
||||
```
|
||||
|
||||
**Create message with system prompt:**
|
||||
```
|
||||
http(method="POST", url="https://api.anthropic.com/v1/messages", headers=[{"name": "x-api-key","value": "{ANTHROPIC_API_KEY}"},{"name": "anthropic-version","value": "2023-06-01"}], body={"model": "claude-sonnet-4-20250514","max_tokens": 1024,"system": "You are a helpful assistant.","messages": [{"role": "user","content": "Explain quantum computing"}]})
|
||||
```
|
||||
|
||||
**List models:**
|
||||
```
|
||||
http(method="GET", url="https://api.anthropic.com/v1/models")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Always include `anthropic-version: 2023-06-01` header.
|
||||
- Models: `claude-sonnet-4-20250514`, `claude-haiku-4-5-20251001`, `claude-opus-4-20250514`.
|
||||
- Max tokens is required for all message requests.
|
||||
- Streaming: set `stream: true` in body.
|
||||
@@ -1,55 +0,0 @@
|
||||
---
|
||||
name: apify
|
||||
version: "1.0.0"
|
||||
description: Apify API — Apify is a full‑stack web scraping and browser automation platform where develop
|
||||
activation:
|
||||
keywords:
|
||||
- "apify"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)apify"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [APIFY_API_KEY]
|
||||
---
|
||||
|
||||
# Apify API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.apify.com/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**List actors:**
|
||||
```
|
||||
http(method="GET", url="https://api.apify.com/v2/acts?limit=10")
|
||||
```
|
||||
|
||||
**Run actor:**
|
||||
```
|
||||
http(method="POST", url="https://api.apify.com/v2/acts/{actor_id}/runs", body={"memory": 256,"timeout": 60})
|
||||
```
|
||||
|
||||
**Get run details:**
|
||||
```
|
||||
http(method="GET", url="https://api.apify.com/v2/acts/{actor_id}/runs/{run_id}")
|
||||
```
|
||||
|
||||
**Get dataset items:**
|
||||
```
|
||||
http(method="GET", url="https://api.apify.com/v2/datasets/{dataset_id}/items?limit=100")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Actor IDs look like `username~actor-name` or a hash.
|
||||
- Run status: `READY`, `RUNNING`, `SUCCEEDED`, `FAILED`, `TIMED-OUT`, `ABORTED`.
|
||||
- Default dataset is created per run; check `defaultDatasetId` in run details.
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
name: apollo
|
||||
version: "1.0.0"
|
||||
description: Apollo API — Apollo is a sales intelligence and engagement platform that helps teams find and
|
||||
activation:
|
||||
keywords:
|
||||
- "apollo"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)apollo"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Apollo API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.apollo.io/api/v1`
|
||||
|
||||
## Actions
|
||||
|
||||
**Search people:**
|
||||
```
|
||||
http(method="POST", url="https://api.apollo.io/api/v1/mixed_people/search", body={"person_titles": ["CEO"],"person_locations": ["San Francisco"],"page": 1,"per_page": 10})
|
||||
```
|
||||
|
||||
**Search organizations:**
|
||||
```
|
||||
http(method="POST", url="https://api.apollo.io/api/v1/mixed_companies/search", body={"organization_locations": ["United States"],"page": 1,"per_page": 10})
|
||||
```
|
||||
|
||||
**Get person:**
|
||||
```
|
||||
http(method="GET", url="https://api.apollo.io/api/v1/people/{person_id}")
|
||||
```
|
||||
|
||||
**Enrich person:**
|
||||
```
|
||||
http(method="POST", url="https://api.apollo.io/api/v1/people/match", body={"email": "[email protected]"})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- API key goes in the request body as `api_key` or as a header.
|
||||
- Search supports filters: `person_titles`, `person_locations`, `organization_domains`.
|
||||
- Rate limit: 50 requests per minute on free tier.
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
name: asana
|
||||
version: "1.0.0"
|
||||
description: Asana REST API — tasks, projects, sections, comments, search
|
||||
activation:
|
||||
keywords:
|
||||
- "asana"
|
||||
- "asana task"
|
||||
- "asana project"
|
||||
exclude_keywords:
|
||||
- "jira"
|
||||
- "trello"
|
||||
patterns:
|
||||
- "(?i)asana.*(task|project|section)"
|
||||
- "(?i)(create|list|update|complete).*asana"
|
||||
tags:
|
||||
- "project-management"
|
||||
- "task-management"
|
||||
max_context_tokens: 1500
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [ASANA_ACCESS_TOKEN]
|
||||
---
|
||||
|
||||
# Asana REST API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected for `app.asana.com`.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://app.asana.com/api/1.0`
|
||||
|
||||
## Actions
|
||||
|
||||
**List my tasks:**
|
||||
```
|
||||
http(method="GET", url="https://app.asana.com/api/1.0/user_task_lists/me/tasks?workspace=<workspace_gid>&opt_fields=name,completed,due_on,assignee_section.name&limit=20")
|
||||
```
|
||||
|
||||
**Get task:**
|
||||
```
|
||||
http(method="GET", url="https://app.asana.com/api/1.0/tasks/<task_gid>?opt_fields=name,notes,completed,due_on,assignee.name,projects.name,tags.name")
|
||||
```
|
||||
|
||||
**Create task:**
|
||||
```
|
||||
http(method="POST", url="https://app.asana.com/api/1.0/tasks", body={"data": {"name": "Task title", "notes": "Description", "projects": ["<project_gid>"], "due_on": "2026-04-01", "assignee": "me"}})
|
||||
```
|
||||
|
||||
**Update task:**
|
||||
```
|
||||
http(method="PUT", url="https://app.asana.com/api/1.0/tasks/<task_gid>", body={"data": {"completed": true}})
|
||||
```
|
||||
|
||||
**List project tasks:**
|
||||
```
|
||||
http(method="GET", url="https://app.asana.com/api/1.0/projects/<project_gid>/tasks?opt_fields=name,completed,due_on,assignee.name&limit=50")
|
||||
```
|
||||
|
||||
**Add comment:**
|
||||
```
|
||||
http(method="POST", url="https://app.asana.com/api/1.0/tasks/<task_gid>/stories", body={"data": {"text": "Comment text"}})
|
||||
```
|
||||
|
||||
**Search tasks:**
|
||||
```
|
||||
http(method="GET", url="https://app.asana.com/api/1.0/workspaces/<workspace_gid>/tasks/search?text=search+term&opt_fields=name,completed&limit=20")
|
||||
```
|
||||
|
||||
**List projects:**
|
||||
```
|
||||
http(method="GET", url="https://app.asana.com/api/1.0/projects?workspace=<workspace_gid>&opt_fields=name,current_status&limit=50")
|
||||
```
|
||||
|
||||
**List workspaces:**
|
||||
```
|
||||
http(method="GET", url="https://app.asana.com/api/1.0/workspaces")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- All response data is wrapped in `{"data": ...}`. Errors: `{"errors": [{"message": "..."}]}`.
|
||||
- Use `opt_fields` to request specific fields (comma-separated). Without it, you get minimal data.
|
||||
- GIDs are numeric strings like `"1234567890123456"`.
|
||||
- Dates are ISO format `YYYY-MM-DD`. Due times use `due_at` (ISO 8601 with timezone).
|
||||
- Pagination: `offset` token from `next_page.offset`. Check `next_page` for more.
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
name: attio
|
||||
version: "1.0.0"
|
||||
description: Attio API — Attio is a modern CRM platform that offers fully customizable workspaces
|
||||
activation:
|
||||
keywords:
|
||||
- "attio"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)attio"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
- "CRM"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Attio API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.attio.com/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**List records:**
|
||||
```
|
||||
http(method="POST", url="https://api.attio.com/v2/objects/{object_slug}/records/query", body={"limit": 20})
|
||||
```
|
||||
|
||||
**Get record:**
|
||||
```
|
||||
http(method="GET", url="https://api.attio.com/v2/objects/{object_slug}/records/{record_id}")
|
||||
```
|
||||
|
||||
**Create record:**
|
||||
```
|
||||
http(method="POST", url="https://api.attio.com/v2/objects/{object_slug}/records", body={"data": {"values": {"name": [{"value": "Acme Corp"}]}}})
|
||||
```
|
||||
|
||||
**List objects:**
|
||||
```
|
||||
http(method="GET", url="https://api.attio.com/v2/objects")
|
||||
```
|
||||
|
||||
**List lists:**
|
||||
```
|
||||
http(method="GET", url="https://api.attio.com/v2/lists")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Standard objects: `companies`, `people`, `deals`.
|
||||
- Values are arrays of typed entries: `[{"value": "..."}]`.
|
||||
- Use `/objects/{slug}/records/query` with filters for searching.
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
name: auth0-management
|
||||
version: "1.0.0"
|
||||
description: Auth0 Management API — Auth0 delivers a flexible, drop-in authentication and authorization platform tha
|
||||
activation:
|
||||
keywords:
|
||||
- "auth0-management"
|
||||
- "auth0 management"
|
||||
- "authentication"
|
||||
patterns:
|
||||
- "(?i)auth0.?management"
|
||||
tags:
|
||||
- "tools"
|
||||
- "authentication"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [AUTH0_API_TOKEN, AUTH0_MANAGEMENT_TENANT_DOMAIN]
|
||||
---
|
||||
|
||||
# Auth0 Management API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://{AUTH0_DOMAIN}/api/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**List users:**
|
||||
```
|
||||
http(method="GET", url="https://{AUTH0_DOMAIN}/api/v2/users?page=0&per_page=10")
|
||||
```
|
||||
|
||||
**Get user:**
|
||||
```
|
||||
http(method="GET", url="https://{AUTH0_DOMAIN}/api/v2/users/{user_id}")
|
||||
```
|
||||
|
||||
**Create user:**
|
||||
```
|
||||
http(method="POST", url="https://{AUTH0_DOMAIN}/api/v2/users", body={"email": "[email protected]","password": "SecureP@ss1","connection": "Username-Password-Authentication"})
|
||||
```
|
||||
|
||||
**Update user:**
|
||||
```
|
||||
http(method="PATCH", url="https://{AUTH0_DOMAIN}/api/v2/users/{user_id}", body={"name": "John Doe"})
|
||||
```
|
||||
|
||||
**List roles:**
|
||||
```
|
||||
http(method="GET", url="https://{AUTH0_DOMAIN}/api/v2/roles")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- `user_id` is URL-encoded: `auth0|abc123` → `auth0%7Cabc123`.
|
||||
- Connections: `Username-Password-Authentication`, `google-oauth2`, etc.
|
||||
- Use `q` param for Lucene query syntax search: `?q=email:"*@acme.com"`.
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
name: autodesk
|
||||
version: "1.0.0"
|
||||
description: Autodesk API — Autodesk is a global leader in design and engineering software
|
||||
activation:
|
||||
keywords:
|
||||
- "autodesk"
|
||||
- "software"
|
||||
patterns:
|
||||
- "(?i)autodesk"
|
||||
tags:
|
||||
- "software"
|
||||
- "development"
|
||||
- "tools"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Autodesk API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Autodesk is a global leader in design and engineering software, offering a cloud‑connected Design and Make Platform—including AutoCAD, Revit, Fusion 360, and Autodesk Platform Services—that connects d
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **OAuth 2.0**. The token is managed automatically — no manual auth setup required in API calls.
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: ayrshare
|
||||
version: "1.0.0"
|
||||
description: Ayrshare API — Ayrshare provides a unified REST-based social media API that lets developers pro
|
||||
activation:
|
||||
keywords:
|
||||
- "ayrshare"
|
||||
- "social media"
|
||||
patterns:
|
||||
- "(?i)ayrshare"
|
||||
tags:
|
||||
- "social-media"
|
||||
- "social"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [AYRSHARE_API_KEY]
|
||||
---
|
||||
|
||||
# Ayrshare API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `Authorization` header — **never construct auth headers manually**.
|
||||
|
||||
> Ayrshare provides a unified REST-based social media API that lets developers programmatically post, schedule, delete, and analyze content across 13 major networks, manage comments and messages, and au
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `Authorization` header.
|
||||
Format: `Authorization: Bearer ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `AYRSHARE_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
name: basin
|
||||
version: "1.0.0"
|
||||
description: Basin API — Basin is a form backend service that captures form submissions from static sites
|
||||
activation:
|
||||
keywords:
|
||||
- "basin"
|
||||
- "workflow automation"
|
||||
patterns:
|
||||
- "(?i)basin"
|
||||
tags:
|
||||
- "tools"
|
||||
- "workflow-automation"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BASIN_API_KEY]
|
||||
---
|
||||
|
||||
# Basin API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `api_token` query parameter.
|
||||
|
||||
> Basin is a form backend service that captures form submissions from static sites and forwards data to email, webhooks or integrations—enabling developers to handle form data without building a custom
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `api_token`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BASIN_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,55 +0,0 @@
|
||||
---
|
||||
name: beehiiv
|
||||
version: "1.0.0"
|
||||
description: Beehiiv API — Beehiiv is a newsletter platform designed for creators and publishers to grow
|
||||
activation:
|
||||
keywords:
|
||||
- "beehiiv"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)beehiiv"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BEEHIIV_API_KEY]
|
||||
---
|
||||
|
||||
# Beehiiv API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.beehiiv.com/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**List publications:**
|
||||
```
|
||||
http(method="GET", url="https://api.beehiiv.com/v2/publications")
|
||||
```
|
||||
|
||||
**List subscribers:**
|
||||
```
|
||||
http(method="GET", url="https://api.beehiiv.com/v2/publications/{pub_id}/subscriptions?limit=10")
|
||||
```
|
||||
|
||||
**Create subscriber:**
|
||||
```
|
||||
http(method="POST", url="https://api.beehiiv.com/v2/publications/{pub_id}/subscriptions", body={"email": "[email protected]","reactivate_existing": true})
|
||||
```
|
||||
|
||||
**List posts:**
|
||||
```
|
||||
http(method="GET", url="https://api.beehiiv.com/v2/publications/{pub_id}/posts?status=confirmed&limit=10")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Publication IDs start with `pub_`.
|
||||
- Post status: `draft`, `confirmed` (published), `archived`.
|
||||
- Subscriber status: `active`, `inactive`, `validating`.
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
name: benchmark-email
|
||||
version: "1.0.0"
|
||||
description: Benchmark Email API — Benchmark Email is an intuitive email-marketing platform that enables marketers
|
||||
activation:
|
||||
keywords:
|
||||
- "benchmark-email"
|
||||
- "benchmark email"
|
||||
- "marketing"
|
||||
patterns:
|
||||
- "(?i)benchmark.?email"
|
||||
tags:
|
||||
- "marketing"
|
||||
- "email"
|
||||
- "campaigns"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BENCHMARK_EMAIL_AUTH_TOKEN]
|
||||
---
|
||||
|
||||
# Benchmark Email API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `AuthToken` header — **never construct auth headers manually**.
|
||||
|
||||
> Benchmark Email is an intuitive email-marketing platform that enables marketers to design mobile-responsive campaigns with drag-and-drop ease, segment contacts for targeted sends, and track real-time
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `AuthToken` header.
|
||||
Format: `AuthToken: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BENCHMARK_EMAIL_AUTH_TOKEN` — Auth Token
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
name: benzinga
|
||||
version: "1.0.0"
|
||||
description: Benzinga API — A real-time financial news and market data service that delivers breaking market
|
||||
activation:
|
||||
keywords:
|
||||
- "benzinga"
|
||||
- "financial data"
|
||||
patterns:
|
||||
- "(?i)benzinga"
|
||||
tags:
|
||||
- "tools"
|
||||
- "financial-data"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BENZINGA_API_KEY]
|
||||
---
|
||||
|
||||
# Benzinga API
|
||||
|
||||
Use the `http` tool. API key is automatically injected as `token` query parameter.
|
||||
|
||||
> A real-time financial news and market data service that delivers breaking market updates, analysis, earnings, and trading insights to investors, traders, and finance professionals.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **query parameter** authentication via `token`.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BENZINGA_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: better-proposals
|
||||
version: "1.0.0"
|
||||
description: Better Proposals API — A web-based platform that enables businesses to create, customize, send
|
||||
activation:
|
||||
keywords:
|
||||
- "better-proposals"
|
||||
- "better proposals"
|
||||
- "proposal software"
|
||||
patterns:
|
||||
- "(?i)better.?proposals"
|
||||
tags:
|
||||
- "tools"
|
||||
- "proposal-software"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BETTER_PROPOSALS_API_TOKEN]
|
||||
---
|
||||
|
||||
# Better Proposals API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `Bptoken` header — **never construct auth headers manually**.
|
||||
|
||||
> A web-based platform that enables businesses to create, customize, send, and track professional sales proposals and contracts with interactive elements, e-signatures, and analytics to streamline clien
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `Bptoken` header.
|
||||
Format: `Bptoken: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BETTER_PROPOSALS_API_TOKEN` — API Token
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
name: big-commerce
|
||||
version: "1.0.0"
|
||||
description: BigCommerce API — BigCommerce is an open SaaS eCommerce platform that enables businesses to build
|
||||
activation:
|
||||
keywords:
|
||||
- "big-commerce"
|
||||
- "bigcommerce"
|
||||
- "ecommerce"
|
||||
patterns:
|
||||
- "(?i)big.?commerce"
|
||||
tags:
|
||||
- "tools"
|
||||
- "ecommerce"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BIG_COMMERCE_STORE_HASH, BIG_COMMERCE_ACCESS_TOKEN]
|
||||
---
|
||||
|
||||
# BigCommerce API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `X-Auth-Token` header — **never construct auth headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.bigcommerce.com/stores/{BIGCOMMERCE_STORE_HASH}/v3`
|
||||
|
||||
## Actions
|
||||
|
||||
**List products:**
|
||||
```
|
||||
http(method="GET", url="https://api.bigcommerce.com/stores/{BIGCOMMERCE_STORE_HASH}/v3/catalog/products?limit=10")
|
||||
```
|
||||
|
||||
**Get product:**
|
||||
```
|
||||
http(method="GET", url="https://api.bigcommerce.com/stores/{BIGCOMMERCE_STORE_HASH}/v3/catalog/products/{product_id}")
|
||||
```
|
||||
|
||||
**Create product:**
|
||||
```
|
||||
http(method="POST", url="https://api.bigcommerce.com/stores/{BIGCOMMERCE_STORE_HASH}/v3/catalog/products", body={"name": "Widget","type": "physical","weight": 1.0,"price": 29.99})
|
||||
```
|
||||
|
||||
**List orders:**
|
||||
```
|
||||
http(method="GET", url="https://api.bigcommerce.com/stores/{BIGCOMMERCE_STORE_HASH}/v3/orders?limit=10")
|
||||
```
|
||||
|
||||
**List customers:**
|
||||
```
|
||||
http(method="GET", url="https://api.bigcommerce.com/stores/{BIGCOMMERCE_STORE_HASH}/v3/customers?limit=10")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Auth via `X-Auth-Token` header (auto-injected).
|
||||
- Products have `type`: `physical`, `digital`.
|
||||
- Prices are decimals, weights in the store's configured unit.
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
name: bigquery
|
||||
version: "1.0.0"
|
||||
description: BigQuery API — BigQuery is a serverless, highly scalable
|
||||
activation:
|
||||
keywords:
|
||||
- "bigquery"
|
||||
- "ai"
|
||||
patterns:
|
||||
- "(?i)bigquery"
|
||||
tags:
|
||||
- "ai"
|
||||
- "machine-learning"
|
||||
- "storage"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# BigQuery API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://bigquery.googleapis.com/bigquery/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**List datasets:**
|
||||
```
|
||||
http(method="GET", url="https://bigquery.googleapis.com/bigquery/v2/projects/{project_id}/datasets")
|
||||
```
|
||||
|
||||
**List tables:**
|
||||
```
|
||||
http(method="GET", url="https://bigquery.googleapis.com/bigquery/v2/projects/{project_id}/datasets/{dataset_id}/tables")
|
||||
```
|
||||
|
||||
**Run query:**
|
||||
```
|
||||
http(method="POST", url="https://bigquery.googleapis.com/bigquery/v2/projects/{project_id}/queries", body={"query": "SELECT * FROM `project.dataset.table` LIMIT 10","useLegacySql": false})
|
||||
```
|
||||
|
||||
**Get query results:**
|
||||
```
|
||||
http(method="GET", url="https://bigquery.googleapis.com/bigquery/v2/projects/{project_id}/queries/{job_id}")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Uses OAuth 2.0 — credentials are auto-injected.
|
||||
- Queries use Standard SQL by default (`useLegacySql: false`).
|
||||
- Large results: check `jobComplete` field; poll with `getQueryResults` if `false`.
|
||||
- Table references: `project.dataset.table`.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: blaze-meter-functional
|
||||
version: "1.0.0"
|
||||
description: BlazeMeter Functional API — BlazeMeter is a testing platform for web and API applications
|
||||
activation:
|
||||
keywords:
|
||||
- "blaze-meter-functional"
|
||||
- "blazemeter functional"
|
||||
- "developer tool"
|
||||
patterns:
|
||||
- "(?i)blaze.?meter.?functional"
|
||||
tags:
|
||||
- "tools"
|
||||
- "developer-tool"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BLAZE_METER_FUNCTIONAL_API_KEY, BLAZE_METER_FUNCTIONAL_API_SECRET, BLAZE_METER_ACCOUNT_ID]
|
||||
---
|
||||
|
||||
# BlazeMeter Functional API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
> BlazeMeter is a testing platform for web and API applications, and its Functional API enables developers to programmatically create, manage, and run automated API tests to validate responses, workflow
|
||||
|
||||
## Authentication
|
||||
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BLAZE_METER_FUNCTIONAL_API_KEY` — API Key
|
||||
- `BLAZE_METER_FUNCTIONAL_API_SECRET` — API Secret
|
||||
- `BLAZE_METER_ACCOUNT_ID` — Account ID
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: blaze-meter-performance
|
||||
version: "1.0.0"
|
||||
description: BlazeMeter Performance API — BlazeMeter is a testing platform for web and API applications
|
||||
activation:
|
||||
keywords:
|
||||
- "blaze-meter-performance"
|
||||
- "blazemeter performance"
|
||||
- "developer tool"
|
||||
patterns:
|
||||
- "(?i)blaze.?meter.?performance"
|
||||
tags:
|
||||
- "tools"
|
||||
- "developer-tool"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BLAZE_METER_PERFORMANCE_API_KEY, BLAZE_METER_PERFORMANCE_API_SECRET]
|
||||
---
|
||||
|
||||
# BlazeMeter Performance API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
> BlazeMeter is a testing platform for web and API applications, and its Performance API enables developers to programmatically create, configure, run, and retrieve results from large-scale performance
|
||||
|
||||
## Authentication
|
||||
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BLAZE_METER_PERFORMANCE_API_KEY` — API Key
|
||||
- `BLAZE_METER_PERFORMANCE_API_SECRET` — API Secret
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: blaze-meter-service-virtualization
|
||||
version: "1.0.0"
|
||||
description: BlazeMeter Service Virtualization API — BlazeMeter is a testing platform for web and API applications
|
||||
activation:
|
||||
keywords:
|
||||
- "blaze-meter-service-virtualization"
|
||||
- "blazemeter service virtualization"
|
||||
- "developer tool"
|
||||
patterns:
|
||||
- "(?i)blaze.?meter.?service.?virtualization"
|
||||
tags:
|
||||
- "tools"
|
||||
- "developer-tool"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BLAZE_METER_SERVICE_VIRTUALIZATION_API_KEY, BLAZE_METER_SERVICE_VIRTUALIZATION_API_SECRET]
|
||||
---
|
||||
|
||||
# BlazeMeter Service Virtualization API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
> BlazeMeter is a testing platform for web and API applications, and its Service Virtualization API enables developers to programmatically create and manage virtual services that simulate APIs and syste
|
||||
|
||||
## Authentication
|
||||
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BLAZE_METER_SERVICE_VIRTUALIZATION_API_KEY` — API Key
|
||||
- `BLAZE_METER_SERVICE_VIRTUALIZATION_API_SECRET` — API Secret
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
name: bluebeam
|
||||
version: "1.0.0"
|
||||
description: Bluebeam API — Bluebeam is a PDF-centric collaboration platform tailored for architecture
|
||||
activation:
|
||||
keywords:
|
||||
- "bluebeam"
|
||||
- "software"
|
||||
patterns:
|
||||
- "(?i)bluebeam"
|
||||
tags:
|
||||
- "software"
|
||||
- "development"
|
||||
- "tools"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Bluebeam API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Bluebeam is a PDF-centric collaboration platform tailored for architecture, engineering, and construction professionals, offering industry-grade markup, measurement, takeoff, and document management t
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **OAuth 2.0**. The token is managed automatically — no manual auth setup required in API calls.
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
name: bluesky
|
||||
version: "1.0.0"
|
||||
description: Bluesky API — Bluesky is a decentralized social media platform built on the open-source AT Pro
|
||||
activation:
|
||||
keywords:
|
||||
- "bluesky"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)bluesky"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BLUESKY_ACCESS_TOKEN, BLUESKY_ENTRYWAY]
|
||||
---
|
||||
|
||||
# Bluesky API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://bsky.social/xrpc`
|
||||
|
||||
## Actions
|
||||
|
||||
**Create session (login):**
|
||||
```
|
||||
http(method="POST", url="https://bsky.social/xrpc/com.atproto.server.createSession", body={"identifier": "your.handle","password": "app-password"})
|
||||
```
|
||||
|
||||
**Create post:**
|
||||
```
|
||||
http(method="POST", url="https://bsky.social/xrpc/com.atproto.repo.createRecord", body={"repo": "did:plc:xxx","collection": "app.bsky.feed.post","record": {"text": "Hello Bluesky!","$type": "app.bsky.feed.post","createdAt": "2026-03-27T00:00:00Z"}})
|
||||
```
|
||||
|
||||
**Get profile:**
|
||||
```
|
||||
http(method="GET", url="https://bsky.social/xrpc/app.bsky.actor.getProfile?actor=your.handle")
|
||||
```
|
||||
|
||||
**Get timeline:**
|
||||
```
|
||||
http(method="GET", url="https://bsky.social/xrpc/app.bsky.feed.getTimeline?limit=20")
|
||||
```
|
||||
|
||||
**Search posts:**
|
||||
```
|
||||
http(method="GET", url="https://bsky.social/xrpc/app.bsky.feed.searchPosts?q=search+term&limit=10")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- First create a session to get an access token.
|
||||
- Posts are AT Protocol records in collection `app.bsky.feed.post`.
|
||||
- Handles look like `username.bsky.social` or custom domains.
|
||||
- DIDs are persistent identifiers: `did:plc:xxxxx`.
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
name: bookingmood
|
||||
version: "1.0.0"
|
||||
description: Bookingmood API — A flexible booking platform that lets rental and vacation property owners embed
|
||||
activation:
|
||||
keywords:
|
||||
- "bookingmood"
|
||||
- "booking software"
|
||||
patterns:
|
||||
- "(?i)bookingmood"
|
||||
tags:
|
||||
- "tools"
|
||||
- "booking-software"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BOOKINGMOOD_API_KEY]
|
||||
---
|
||||
|
||||
# Bookingmood API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> A flexible booking platform that lets rental and vacation property owners embed customizable calendars on their websites, manage availability and reservations, track payments, sync with external calen
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **Bearer Token** authentication. The token is injected automatically into the `Authorization` header.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BOOKINGMOOD_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: bot-star
|
||||
version: "1.0.0"
|
||||
description: BotStar API — A visual bot-building platform that enables businesses to design, deploy
|
||||
activation:
|
||||
keywords:
|
||||
- "bot-star"
|
||||
- "botstar"
|
||||
- "chatbot builder"
|
||||
patterns:
|
||||
- "(?i)bot.?star"
|
||||
tags:
|
||||
- "tools"
|
||||
- "chatbot-builder"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BOT_STAR_API_TOKEN]
|
||||
---
|
||||
|
||||
# BotStar API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> A visual bot-building platform that enables businesses to design, deploy, and manage AI-powered chatbots for websites, messaging apps, and customer support workflows without coding.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **Bearer Token** authentication. The token is injected automatically into the `Authorization` header.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BOT_STAR_API_TOKEN` — API Token
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: bouncer
|
||||
version: "1.0.0"
|
||||
description: Bouncer API — A cloud-based platform that verifies and cleans email lists by identifying inval
|
||||
activation:
|
||||
keywords:
|
||||
- "bouncer"
|
||||
- "email verification"
|
||||
patterns:
|
||||
- "(?i)bouncer"
|
||||
tags:
|
||||
- "tools"
|
||||
- "email-verification"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BOUNCER_API_KEY]
|
||||
---
|
||||
|
||||
# Bouncer API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `x-api-key` header — **never construct auth headers manually**.
|
||||
|
||||
> A cloud-based platform that verifies and cleans email lists by identifying invalid, risky, or disposable email addresses to improve deliverability, reduce bounce rates, and enhance email campaign perf
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `x-api-key` header.
|
||||
Format: `x-api-key: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BOUNCER_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: box-hero
|
||||
version: "1.0.0"
|
||||
description: BoxHero API — A cloud-based inventory and stock management platform that enables businesses to
|
||||
activation:
|
||||
keywords:
|
||||
- "box-hero"
|
||||
- "boxhero"
|
||||
- "inventory management"
|
||||
patterns:
|
||||
- "(?i)box.?hero"
|
||||
tags:
|
||||
- "tools"
|
||||
- "inventory-management"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BOX_HERO_API_TOKEN]
|
||||
---
|
||||
|
||||
# BoxHero API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> A cloud-based inventory and stock management platform that enables businesses to track products, manage warehouses, monitor stock levels in real time, and automate order fulfillment across sales chann
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **Bearer Token** authentication. The token is injected automatically into the `Authorization` header.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BOX_HERO_API_TOKEN` — API Token
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
name: box
|
||||
version: "1.0.0"
|
||||
description: Box API — files, folders, collaborations, search, comments
|
||||
activation:
|
||||
keywords:
|
||||
- "box"
|
||||
- "box.com"
|
||||
- "box file"
|
||||
exclude_keywords:
|
||||
- "dropbox"
|
||||
- "google drive"
|
||||
patterns:
|
||||
- "(?i)box\\.com.*(file|folder|share)"
|
||||
- "(?i)(upload|download|share).*box"
|
||||
tags:
|
||||
- "file-storage"
|
||||
- "cloud-storage"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BOX_ACCESS_TOKEN]
|
||||
---
|
||||
|
||||
# Box Content API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected for `api.box.com`.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.box.com/2.0`
|
||||
|
||||
## Actions
|
||||
|
||||
**Get folder items:**
|
||||
```
|
||||
http(method="GET", url="https://api.box.com/2.0/folders/<folder_id>/items?fields=id,name,type,modified_at,size&limit=20")
|
||||
```
|
||||
Root folder ID is `"0"`.
|
||||
|
||||
**Get file info:**
|
||||
```
|
||||
http(method="GET", url="https://api.box.com/2.0/files/<file_id>?fields=id,name,size,modified_at,shared_link")
|
||||
```
|
||||
|
||||
**Search:**
|
||||
```
|
||||
http(method="GET", url="https://api.box.com/2.0/search?query=report&type=file&limit=20")
|
||||
```
|
||||
|
||||
**Create folder:**
|
||||
```
|
||||
http(method="POST", url="https://api.box.com/2.0/folders", body={"name": "New Folder", "parent": {"id": "0"}})
|
||||
```
|
||||
|
||||
**Copy file:**
|
||||
```
|
||||
http(method="POST", url="https://api.box.com/2.0/files/<file_id>/copy", body={"parent": {"id": "<folder_id>"}})
|
||||
```
|
||||
|
||||
**Create shared link:**
|
||||
```
|
||||
http(method="PUT", url="https://api.box.com/2.0/files/<file_id>?fields=shared_link", body={"shared_link": {"access": "open"}})
|
||||
```
|
||||
|
||||
**Add collaboration:**
|
||||
```
|
||||
http(method="POST", url="https://api.box.com/2.0/collaborations", body={"item": {"type": "folder", "id": "<folder_id>"}, "accessible_by": {"type": "user", "login": "[email protected]"}, "role": "editor"})
|
||||
```
|
||||
|
||||
**Add comment:**
|
||||
```
|
||||
http(method="POST", url="https://api.box.com/2.0/comments", body={"item": {"type": "file", "id": "<file_id>"}, "message": "Please review"})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Root folder is always `"0"`.
|
||||
- Collaboration roles: `editor`, `viewer`, `previewer`, `uploader`, `co-owner`.
|
||||
- Shared link access: `open` (anyone), `company` (organization), `collaborators` (invited only).
|
||||
- Use `fields` param to request specific properties.
|
||||
- Pagination: `offset` + `limit`. Check `total_count`.
|
||||
- File uploads use `https://upload.box.com/api/2.0/files/content` (different host).
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: breathe
|
||||
version: "1.0.0"
|
||||
description: Breathe API — Breathe is a cloud-based HR software designed for small and medium-sized busines
|
||||
activation:
|
||||
keywords:
|
||||
- "breathe"
|
||||
- "hris"
|
||||
patterns:
|
||||
- "(?i)breathe"
|
||||
tags:
|
||||
- "tools"
|
||||
- "hris"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BREATHE_API_KEY]
|
||||
---
|
||||
|
||||
# Breathe API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `X-API-KEY` header — **never construct auth headers manually**.
|
||||
|
||||
> Breathe is a cloud-based HR software designed for small and medium-sized businesses, providing tools for managing employee records, leave requests, performance reviews, document storage, and reporting
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `X-API-KEY` header.
|
||||
Format: `X-API-KEY: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BREATHE_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,76 +0,0 @@
|
||||
---
|
||||
name: brevo
|
||||
version: "1.0.0"
|
||||
description: Brevo (Sendinblue) API — email campaigns, contacts, transactional email, SMS
|
||||
activation:
|
||||
keywords:
|
||||
- "brevo"
|
||||
- "sendinblue"
|
||||
- "email campaign"
|
||||
exclude_keywords:
|
||||
- "mailchimp"
|
||||
- "resend"
|
||||
patterns:
|
||||
- "(?i)(brevo|sendinblue).*(email|contact|campaign|sms)"
|
||||
tags:
|
||||
- "email"
|
||||
- "marketing"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BREVO_API_KEY]
|
||||
---
|
||||
|
||||
# Brevo API (formerly Sendinblue)
|
||||
|
||||
Use the `http` tool. Include `api-key` header.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.brevo.com/v3`
|
||||
|
||||
## Actions
|
||||
|
||||
**Send transactional email:**
|
||||
```
|
||||
http(method="POST", url="https://api.brevo.com/v3/smtp/email", headers=[{"name": "api-key", "value": "{BREVO_API_KEY}"}], body={"sender": {"name": "My App", "email": "[email protected]"}, "to": [{"email": "[email protected]", "name": "John"}], "subject": "Welcome!", "htmlContent": "<h1>Hello John</h1><p>Welcome aboard.</p>"})
|
||||
```
|
||||
|
||||
**List contacts:**
|
||||
```
|
||||
http(method="GET", url="https://api.brevo.com/v3/contacts?limit=20&offset=0", headers=[{"name": "api-key", "value": "{BREVO_API_KEY}"}])
|
||||
```
|
||||
|
||||
**Create contact:**
|
||||
```
|
||||
http(method="POST", url="https://api.brevo.com/v3/contacts", headers=[{"name": "api-key", "value": "{BREVO_API_KEY}"}], body={"email": "[email protected]", "attributes": {"FIRSTNAME": "Alice", "LASTNAME": "Smith"}, "listIds": [1]})
|
||||
```
|
||||
|
||||
**Update contact:**
|
||||
```
|
||||
http(method="PUT", url="https://api.brevo.com/v3/contacts/[email protected]", headers=[{"name": "api-key", "value": "{BREVO_API_KEY}"}], body={"attributes": {"FIRSTNAME": "Updated"}})
|
||||
```
|
||||
|
||||
**List email campaigns:**
|
||||
```
|
||||
http(method="GET", url="https://api.brevo.com/v3/emailCampaigns?limit=20&status=sent", headers=[{"name": "api-key", "value": "{BREVO_API_KEY}"}])
|
||||
```
|
||||
|
||||
**Get campaign stats:**
|
||||
```
|
||||
http(method="GET", url="https://api.brevo.com/v3/emailCampaigns/<campaign_id>", headers=[{"name": "api-key", "value": "{BREVO_API_KEY}"}])
|
||||
```
|
||||
|
||||
**Send SMS:**
|
||||
```
|
||||
http(method="POST", url="https://api.brevo.com/v3/transactionalSMS/sms", headers=[{"name": "api-key", "value": "{BREVO_API_KEY}"}], body={"sender": "MyApp", "recipient": "+1234567890", "content": "Your code is 123456", "type": "transactional"})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Contact attributes are uppercase: `FIRSTNAME`, `LASTNAME`, `SMS`.
|
||||
- `listIds` are integer IDs of contact lists.
|
||||
- Campaign statuses: `draft`, `sent`, `queued`, `suspended`, `in_process`.
|
||||
- Pagination: `limit` + `offset`. Check `count` for total.
|
||||
- Transactional email returns `messageId` for tracking.
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
name: brex
|
||||
version: "1.0.0"
|
||||
description: Brex API — Brex combines corporate cards, business accounts, expense management, bill pay
|
||||
activation:
|
||||
keywords:
|
||||
- "brex"
|
||||
- "finance"
|
||||
patterns:
|
||||
- "(?i)brex"
|
||||
tags:
|
||||
- "tools"
|
||||
- "finance"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Brex API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Brex combines corporate cards, business accounts, expense management, bill pay, and travel booking into a single AI-powered financial operations platform—offering unified spend control, real-time visi
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **OAuth 2.0**. The token is managed automatically — no manual auth setup required in API calls.
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: bright-data
|
||||
version: "1.0.0"
|
||||
description: BrightData API — Bright Data (formerly Luminati) is a comprehensive web data platform offering a
|
||||
activation:
|
||||
keywords:
|
||||
- "bright-data"
|
||||
- "brightdata"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)bright.?data"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BRIGHT_DATA_API_KEY]
|
||||
---
|
||||
|
||||
# BrightData API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Bright Data (formerly Luminati) is a comprehensive web data platform offering a global proxy network (residential, mobile, ISP, data center), browser-based scraping, SERP APIs, and managed data pipeli
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **Bearer Token** authentication. The token is injected automatically into the `Authorization` header.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BRIGHT_DATA_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: browse-ai
|
||||
version: "1.0.0"
|
||||
description: Browse AI API — Browse AI is a no-code, AI-powered web scraping and monitoring platform that ena
|
||||
activation:
|
||||
keywords:
|
||||
- "browse-ai"
|
||||
- "browse ai"
|
||||
- "scraper"
|
||||
patterns:
|
||||
- "(?i)browse.?ai"
|
||||
tags:
|
||||
- "tools"
|
||||
- "scraper"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BROWSE_AI_API_KEY]
|
||||
---
|
||||
|
||||
# Browse AI API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Browse AI is a no-code, AI-powered web scraping and monitoring platform that enables users to extract structured data from any website, set automated alerts for changes, and funnel the output into spr
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **Bearer Token** authentication. The token is injected automatically into the `Authorization` header.
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BROWSE_AI_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,51 +0,0 @@
|
||||
---
|
||||
name: browserbase
|
||||
version: "1.0.0"
|
||||
description: Browserbase API — Browserbase is a cloud platform that lets developers run headless browsers at sc
|
||||
activation:
|
||||
keywords:
|
||||
- "browserbase"
|
||||
- "ai"
|
||||
patterns:
|
||||
- "(?i)browserbase"
|
||||
tags:
|
||||
- "ai"
|
||||
- "machine-learning"
|
||||
- "storage"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BROWSERBASE_API_KEY]
|
||||
---
|
||||
|
||||
# Browserbase API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `X-BB-API-Key` header — **never construct auth headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.browserbase.com/v1`
|
||||
|
||||
## Actions
|
||||
|
||||
**Create session:**
|
||||
```
|
||||
http(method="POST", url="https://api.browserbase.com/v1/sessions", body={"projectId": "<project_id>"})
|
||||
```
|
||||
|
||||
**List sessions:**
|
||||
```
|
||||
http(method="GET", url="https://api.browserbase.com/v1/sessions?limit=10")
|
||||
```
|
||||
|
||||
**Get session:**
|
||||
```
|
||||
http(method="GET", url="https://api.browserbase.com/v1/sessions/{session_id}")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Sessions provide a headless browser instance.
|
||||
- Connect via CDP (Chrome DevTools Protocol) using the session's debug URL.
|
||||
- Project ID is required for session creation.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: bug-bug
|
||||
version: "1.0.0"
|
||||
description: BugBug API — A no-code testing platform that automatically crawls websites and web apps to de
|
||||
activation:
|
||||
keywords:
|
||||
- "bug-bug"
|
||||
- "bugbug"
|
||||
- "bug detection"
|
||||
patterns:
|
||||
- "(?i)bug.?bug"
|
||||
tags:
|
||||
- "tools"
|
||||
- "bug-detection"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BUG_BUG_API_KEY]
|
||||
---
|
||||
|
||||
# BugBug API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `Authorization` header — **never construct auth headers manually**.
|
||||
|
||||
> A no-code testing platform that automatically crawls websites and web apps to detect visual issues, broken links, and UI regressions, helping teams maintain quality, catch bugs early, and streamline Q
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `Authorization` header.
|
||||
Format: `Authorization: Token ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BUG_BUG_API_KEY` — API key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: bug-herd
|
||||
version: "1.0.0"
|
||||
description: BugHerd API — A web-based issue and feedback tracking tool that lets teams capture visual bugs
|
||||
activation:
|
||||
keywords:
|
||||
- "bug-herd"
|
||||
- "bugherd"
|
||||
- "bug tracking"
|
||||
patterns:
|
||||
- "(?i)bug.?herd"
|
||||
tags:
|
||||
- "tools"
|
||||
- "bug-tracking"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BUG_HERD_USERNAME, BUG_HERD_PASSWORD]
|
||||
---
|
||||
|
||||
# BugHerd API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
> A web-based issue and feedback tracking tool that lets teams capture visual bugs directly on web pages, annotate problems, manage tickets, and collaborate on fixes for faster design and development cy
|
||||
|
||||
## Authentication
|
||||
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BUG_HERD_USERNAME` — API Key
|
||||
- `BUG_HERD_PASSWORD` — Password
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: byte-forms
|
||||
version: "1.0.0"
|
||||
description: ByteForms API — A no-code form creation tool that enables businesses to design, deploy
|
||||
activation:
|
||||
keywords:
|
||||
- "byte-forms"
|
||||
- "byteforms"
|
||||
- "form builder"
|
||||
patterns:
|
||||
- "(?i)byte.?forms"
|
||||
tags:
|
||||
- "tools"
|
||||
- "form-builder"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [BYTE_FORMS_API_KEY]
|
||||
---
|
||||
|
||||
# ByteForms API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `Authorization` header — **never construct auth headers manually**.
|
||||
|
||||
> A no-code form creation tool that enables businesses to design, deploy, and embed customizable online forms for data collection, surveys, and customer feedback with optional logic and integrations.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `Authorization` header.
|
||||
Format: `Authorization: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `BYTE_FORMS_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
name: calcom
|
||||
version: "1.0.0"
|
||||
description: Cal.com API v2 — event types, bookings, availability, schedules
|
||||
activation:
|
||||
keywords:
|
||||
- "cal.com"
|
||||
- "calcom"
|
||||
- "cal dot com"
|
||||
exclude_keywords:
|
||||
- "calendly"
|
||||
- "google calendar"
|
||||
patterns:
|
||||
- "(?i)cal\\.?com.*(event|booking|availability|schedule)"
|
||||
tags:
|
||||
- "scheduling"
|
||||
- "calendar"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CALCOM_API_KEY]
|
||||
---
|
||||
|
||||
# Cal.com API v2
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected for `api.cal.com`.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.cal.com/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**List event types:**
|
||||
```
|
||||
http(method="GET", url="https://api.cal.com/v2/event-types")
|
||||
```
|
||||
|
||||
**Get event type:**
|
||||
```
|
||||
http(method="GET", url="https://api.cal.com/v2/event-types/<event_type_id>")
|
||||
```
|
||||
|
||||
**List bookings:**
|
||||
```
|
||||
http(method="GET", url="https://api.cal.com/v2/bookings?status=upcoming&take=20")
|
||||
```
|
||||
|
||||
**Get booking:**
|
||||
```
|
||||
http(method="GET", url="https://api.cal.com/v2/bookings/<booking_uid>")
|
||||
```
|
||||
|
||||
**Create booking:**
|
||||
```
|
||||
http(method="POST", url="https://api.cal.com/v2/bookings", body={"eventTypeId": 123, "start": "2026-04-01T10:00:00Z", "attendee": {"name": "John Doe", "email": "[email protected]", "timeZone": "America/New_York"}, "metadata": {}})
|
||||
```
|
||||
|
||||
**Cancel booking:**
|
||||
```
|
||||
http(method="POST", url="https://api.cal.com/v2/bookings/<booking_uid>/cancel", body={"cancellationReason": "Schedule conflict"})
|
||||
```
|
||||
|
||||
**Get availability:**
|
||||
```
|
||||
http(method="GET", url="https://api.cal.com/v2/slots/available?startTime=2026-04-01T00:00:00Z&endTime=2026-04-07T00:00:00Z&eventTypeId=123")
|
||||
```
|
||||
|
||||
**List schedules:**
|
||||
```
|
||||
http(method="GET", url="https://api.cal.com/v2/schedules")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Responses: `{"status": "success", "data": {...}}`.
|
||||
- Booking status: `upcoming`, `recurring`, `past`, `cancelled`, `unconfirmed`.
|
||||
- Times are always UTC (ISO 8601). Attendee specifies their timezone.
|
||||
- Booking UIDs are UUID strings.
|
||||
- Use `take` and `skip` for pagination.
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
name: calendly
|
||||
version: "1.0.0"
|
||||
description: Calendly API v2 — event types, scheduled events, invitees
|
||||
activation:
|
||||
keywords:
|
||||
- "calendly"
|
||||
- "calendly event"
|
||||
- "booking"
|
||||
- "scheduling link"
|
||||
exclude_keywords:
|
||||
- "cal.com"
|
||||
- "google calendar"
|
||||
patterns:
|
||||
- "(?i)calendly.*(event|booking|invitee|schedule)"
|
||||
tags:
|
||||
- "scheduling"
|
||||
- "calendar"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CALENDLY_ACCESS_TOKEN]
|
||||
---
|
||||
|
||||
# Calendly API v2
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected for `api.calendly.com`.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.calendly.com`
|
||||
|
||||
## Actions
|
||||
|
||||
**Get current user:**
|
||||
```
|
||||
http(method="GET", url="https://api.calendly.com/users/me")
|
||||
```
|
||||
|
||||
**List event types:**
|
||||
```
|
||||
http(method="GET", url="https://api.calendly.com/event_types?user=<user_uri>&count=20")
|
||||
```
|
||||
|
||||
**List scheduled events:**
|
||||
```
|
||||
http(method="GET", url="https://api.calendly.com/scheduled_events?user=<user_uri>&min_start_time=2026-03-27T00:00:00Z&max_start_time=2026-04-30T00:00:00Z&status=active&count=20")
|
||||
```
|
||||
|
||||
**Get event details:**
|
||||
```
|
||||
http(method="GET", url="https://api.calendly.com/scheduled_events/<event_uuid>")
|
||||
```
|
||||
|
||||
**List invitees for event:**
|
||||
```
|
||||
http(method="GET", url="https://api.calendly.com/scheduled_events/<event_uuid>/invitees?count=20")
|
||||
```
|
||||
|
||||
**Cancel event:**
|
||||
```
|
||||
http(method="POST", url="https://api.calendly.com/scheduled_events/<event_uuid>/cancellation", body={"reason": "Schedule conflict"})
|
||||
```
|
||||
|
||||
**List organization members:**
|
||||
```
|
||||
http(method="GET", url="https://api.calendly.com/organization_memberships?organization=<org_uri>")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Resources are identified by URIs (e.g., `https://api.calendly.com/users/ABCDEF123456`), not plain IDs.
|
||||
- First call `GET /users/me` to get your `uri` and `current_organization`.
|
||||
- Event status: `active`, `canceled`.
|
||||
- Pagination: use `page_token` from `pagination.next_page_token`.
|
||||
- Dates are ISO 8601 with timezone (UTC recommended).
|
||||
@@ -1,51 +0,0 @@
|
||||
---
|
||||
name: canva
|
||||
version: "1.0.0"
|
||||
description: Canva API — Canva is a cloud-based graphic design platform with a drag‑and‑drop editor
|
||||
activation:
|
||||
keywords:
|
||||
- "canva"
|
||||
- "tools"
|
||||
patterns:
|
||||
- "(?i)canva"
|
||||
tags:
|
||||
- "tools"
|
||||
- "utility"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Canva API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.canva.com/rest/v1`
|
||||
|
||||
## Actions
|
||||
|
||||
**List designs:**
|
||||
```
|
||||
http(method="GET", url="https://api.canva.com/rest/v1/designs?limit=10")
|
||||
```
|
||||
|
||||
**Get design:**
|
||||
```
|
||||
http(method="GET", url="https://api.canva.com/rest/v1/designs/{design_id}")
|
||||
```
|
||||
|
||||
**Create design:**
|
||||
```
|
||||
http(method="POST", url="https://api.canva.com/rest/v1/designs", body={"title": "My Design","design_type": {"type": "preset","name": "doc"}})
|
||||
```
|
||||
|
||||
**Export design:**
|
||||
```
|
||||
http(method="POST", url="https://api.canva.com/rest/v1/designs/{design_id}/exports", body={"format": {"type": "png"}})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Uses OAuth 2.0 — credentials are auto-injected.
|
||||
- Design types: `doc`, `presentation`, `whiteboard`, `social_media`.
|
||||
- Export formats: `png`, `jpg`, `pdf`, `svg`, `mp4`.
|
||||
@@ -1,39 +0,0 @@
|
||||
---
|
||||
name: capsule
|
||||
version: "1.0.0"
|
||||
description: Capsule API — Capsule CRM is a streamlined cloud-based CRM designed for small businesses and s
|
||||
activation:
|
||||
keywords:
|
||||
- "capsule"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)capsule"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
- "CRM"
|
||||
max_context_tokens: 1200
|
||||
---
|
||||
|
||||
# Capsule API
|
||||
|
||||
Use the `http` tool. OAuth credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
> Capsule CRM is a streamlined cloud-based CRM designed for small businesses and sales teams, furnishing contact and organisation management, sales pipelines, tasks, projects, and analytics in one place
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **OAuth 2.0**. The token is managed automatically — no manual auth setup required in API calls.
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
name: cats
|
||||
version: "1.0.0"
|
||||
description: CATS API — CATS is a web-based applicant tracking system designed for recruiting agencies a
|
||||
activation:
|
||||
keywords:
|
||||
- "cats"
|
||||
- "ats"
|
||||
patterns:
|
||||
- "(?i)cats"
|
||||
tags:
|
||||
- "tools"
|
||||
- "ats"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CATS_API_KEY]
|
||||
---
|
||||
|
||||
# CATS API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `authorization` header — **never construct auth headers manually**.
|
||||
|
||||
> CATS is a web-based applicant tracking system designed for recruiting agencies and HR teams, offering tools for job posting, resume parsing, candidate tracking, custom workflows, analytics, and integr
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `authorization` header.
|
||||
Format: `authorization: Token ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `CATS_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
name: central-station-crm
|
||||
version: "1.0.0"
|
||||
description: Central Station CRM API — CentralStationCRM is a lightweight CRM designed for small businesses to manage c
|
||||
activation:
|
||||
keywords:
|
||||
- "central-station-crm"
|
||||
- "central station crm"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)central.?station.?crm"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
- "CRM"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CENTRAL_STATION_CRM_API_KEY]
|
||||
---
|
||||
|
||||
# Central Station CRM API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `X-apikey` header — **never construct auth headers manually**.
|
||||
|
||||
> CentralStationCRM is a lightweight CRM designed for small businesses to manage contacts, track deals, organize tasks and streamline customer relationships with a simple, user-friendly interface.
|
||||
|
||||
## Authentication
|
||||
|
||||
This integration uses **API Key** authentication via the `X-apikey` header.
|
||||
Format: `X-apikey: ...`
|
||||
|
||||
## Required Credentials
|
||||
|
||||
- `CENTRAL_STATION_CRM_API_KEY` — API Key
|
||||
|
||||
## Usage
|
||||
|
||||
Use the `http` tool to call this API. Example:
|
||||
```
|
||||
http(method="GET", url="<api_base_url>/endpoint")
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Do NOT add Authorization headers — automatically injected by the credential system.
|
||||
- Always use HTTPS URLs.
|
||||
@@ -1,65 +0,0 @@
|
||||
---
|
||||
name: chargebee
|
||||
version: "1.0.0"
|
||||
description: Chargebee API — Chargebee is a subscription billing and revenue operations platform that helps S
|
||||
activation:
|
||||
keywords:
|
||||
- "chargebee"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)chargebee"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
- "CRM"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CHARGEBEE_SUBDOMAIN, CHARGEBEE_API_KEY]
|
||||
---
|
||||
|
||||
# Chargebee API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://{CHARGEBEE_SITE}.chargebee.com/api/v2`
|
||||
|
||||
**Content-Type**: `application/x-www-form-urlencoded` for POST/PUT requests.
|
||||
|
||||
## Actions
|
||||
|
||||
**List subscriptions:**
|
||||
```
|
||||
http(method="GET", url="https://{CHARGEBEE_SITE}.chargebee.com/api/v2/subscriptions?limit=10")
|
||||
```
|
||||
|
||||
**Get subscription:**
|
||||
```
|
||||
http(method="GET", url="https://{CHARGEBEE_SITE}.chargebee.com/api/v2/subscriptions/{subscription_id}")
|
||||
```
|
||||
|
||||
**Create subscription:**
|
||||
```
|
||||
http(method="POST", url="https://{CHARGEBEE_SITE}.chargebee.com/api/v2/subscriptions", headers=[{"name": "Content-Type", "value": "application/x-www-form-urlencoded"}], body="customer[email][email protected]&plan_id=basic-monthly")
|
||||
```
|
||||
|
||||
**List customers:**
|
||||
```
|
||||
http(method="GET", url="https://{CHARGEBEE_SITE}.chargebee.com/api/v2/customers?limit=10")
|
||||
```
|
||||
|
||||
**List invoices:**
|
||||
```
|
||||
http(method="GET", url="https://{CHARGEBEE_SITE}.chargebee.com/api/v2/invoices?limit=10&sort_by[asc]=date")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Uses Basic auth with API key as username and empty password.
|
||||
- POST bodies are form-encoded with bracket notation: `customer[email]=...`.
|
||||
- Subscription states: `future`, `in_trial`, `active`, `non_renewing`, `paused`, `cancelled`.
|
||||
- Pagination: `offset` key in response; pass as `?offset=...` for next page.
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
name: circle-ci
|
||||
version: "1.0.0"
|
||||
description: Circle CI API — CircleCI is a continuous integration and delivery (CI/CD) platform that automate
|
||||
activation:
|
||||
keywords:
|
||||
- "circle-ci"
|
||||
- "circle ci"
|
||||
- "devops"
|
||||
patterns:
|
||||
- "(?i)circle.?ci"
|
||||
tags:
|
||||
- "devops"
|
||||
- "ci-cd"
|
||||
- "deployment"
|
||||
- "dev-ops"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CIRCLE_CI_API_KEY]
|
||||
---
|
||||
|
||||
# Circle CI API
|
||||
|
||||
Use the `http` tool. API key is automatically injected via `Circle-Token` header — **never construct auth headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://circleci.com/api/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**Get current user:**
|
||||
```
|
||||
http(method="GET", url="https://circleci.com/api/v2/me")
|
||||
```
|
||||
|
||||
**List pipelines:**
|
||||
```
|
||||
http(method="GET", url="https://circleci.com/api/v2/project/{project_slug}/pipeline?branch=main")
|
||||
```
|
||||
|
||||
**Get pipeline:**
|
||||
```
|
||||
http(method="GET", url="https://circleci.com/api/v2/pipeline/{pipeline_id}")
|
||||
```
|
||||
|
||||
**List workflows:**
|
||||
```
|
||||
http(method="GET", url="https://circleci.com/api/v2/pipeline/{pipeline_id}/workflow")
|
||||
```
|
||||
|
||||
**Trigger pipeline:**
|
||||
```
|
||||
http(method="POST", url="https://circleci.com/api/v2/project/{project_slug}/pipeline", body={"branch": "main","parameters": {}})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Project slug format: `gh/{org}/{repo}` or `bb/{org}/{repo}`.
|
||||
- Pipeline statuses: `created`, `errored`, `setup-pending`, `setup`, `pending`.
|
||||
- Workflow statuses: `success`, `running`, `not_run`, `failed`, `error`, `failing`, `on_hold`, `canceled`.
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
name: clerk
|
||||
version: "1.0.0"
|
||||
description: Clerk API — Clerk provides user authentication and user management solutions for modern web
|
||||
activation:
|
||||
keywords:
|
||||
- "clerk"
|
||||
- "crm"
|
||||
patterns:
|
||||
- "(?i)clerk"
|
||||
tags:
|
||||
- "crm"
|
||||
- "sales"
|
||||
- "contacts"
|
||||
- "CRM"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CLERK_API_KEY]
|
||||
---
|
||||
|
||||
# Clerk API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected — **never construct Authorization headers manually**.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.clerk.com/v1`
|
||||
|
||||
## Actions
|
||||
|
||||
**List users:**
|
||||
```
|
||||
http(method="GET", url="https://api.clerk.com/v1/users?limit=10&order_by=-created_at")
|
||||
```
|
||||
|
||||
**Get user:**
|
||||
```
|
||||
http(method="GET", url="https://api.clerk.com/v1/users/{user_id}")
|
||||
```
|
||||
|
||||
**Create user:**
|
||||
```
|
||||
http(method="POST", url="https://api.clerk.com/v1/users", body={"email_address": ["[email protected]"],"first_name": "John","last_name": "Doe","password": "SecureP@ss1"})
|
||||
```
|
||||
|
||||
**Update user:**
|
||||
```
|
||||
http(method="PATCH", url="https://api.clerk.com/v1/users/{user_id}", body={"first_name": "Jane"})
|
||||
```
|
||||
|
||||
**Delete user:**
|
||||
```
|
||||
http(method="DELETE", url="https://api.clerk.com/v1/users/{user_id}")
|
||||
```
|
||||
|
||||
**List organizations:**
|
||||
```
|
||||
http(method="GET", url="https://api.clerk.com/v1/organizations?limit=10")
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- User IDs start with `user_`.
|
||||
- Email addresses are arrays — users can have multiple.
|
||||
- Use `?query=` for fuzzy search across name/email.
|
||||
- Pagination: `limit` + `offset`.
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
name: click-house
|
||||
version: "1.0.0"
|
||||
description: ClickHouse API — ClickHouse is an ultra-fast, column-oriented database designed for real-time ana
|
||||
activation:
|
||||
keywords:
|
||||
- "click-house"
|
||||
- "clickhouse"
|
||||
- "analytics"
|
||||
patterns:
|
||||
- "(?i)click.?house"
|
||||
tags:
|
||||
- "analytics"
|
||||
- "data"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CLICK_HOUSE_API_KEY, CLICK_HOUSE_SECRET_KEY]
|
||||
---
|
||||
|
||||
# ClickHouse API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://{CLICKHOUSE_HOST}:8443`
|
||||
|
||||
## Actions
|
||||
|
||||
**Run query:**
|
||||
```
|
||||
http(method="POST", url="https://{CLICKHOUSE_HOST}:8443/?query=SELECT+1")
|
||||
```
|
||||
|
||||
**List tables:**
|
||||
```
|
||||
http(method="POST", url="https://{CLICKHOUSE_HOST}:8443/?query=SHOW+TABLES+FROM+default")
|
||||
```
|
||||
|
||||
**Insert data:**
|
||||
```
|
||||
http(method="POST", url="https://{CLICKHOUSE_HOST}:8443/?query=INSERT+INTO+table+FORMAT+JSONEachRow", body=[{"col1": "value1","col2": 42}])
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- ClickHouse uses HTTP interface on port 8443 (HTTPS) or 8123 (HTTP).
|
||||
- Pass SQL in `query` parameter or POST body.
|
||||
- Output formats: `JSON`, `JSONEachRow`, `CSV`, `TSV`.
|
||||
- Auth: Basic auth or `X-ClickHouse-User`/`X-ClickHouse-Key` headers.
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
name: click-send
|
||||
version: "1.0.0"
|
||||
description: ClickSend API — A cloud-based messaging and communication service that enables businesses to sen
|
||||
activation:
|
||||
keywords:
|
||||
- "click-send"
|
||||
- "clicksend"
|
||||
- "communication"
|
||||
patterns:
|
||||
- "(?i)click.?send"
|
||||
tags:
|
||||
- "messaging"
|
||||
- "communication"
|
||||
- "chat"
|
||||
max_context_tokens: 1200
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CLICK_SEND_USERNAME, CLICK_SEND_PASSWORD]
|
||||
---
|
||||
|
||||
# ClickSend API
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://rest.clicksend.com/v3`
|
||||
|
||||
## Actions
|
||||
|
||||
**Send SMS:**
|
||||
```
|
||||
http(method="POST", url="https://rest.clicksend.com/v3/sms/send", body={"messages": [{"to": "+1234567890","body": "Hello!","source": "sdk"}]})
|
||||
```
|
||||
|
||||
**Get SMS history:**
|
||||
```
|
||||
http(method="GET", url="https://rest.clicksend.com/v3/sms/history?page=1&limit=10")
|
||||
```
|
||||
|
||||
**Send email:**
|
||||
```
|
||||
http(method="POST", url="https://rest.clicksend.com/v3/email/send", body={"to": [{"email": "[email protected]","name": "John"}],"from": {"email": "[email protected]"},"subject": "Hello","body": "<p>Content</p>"})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Uses Basic auth with username and API key.
|
||||
- SMS `to` must include country code (e.g., `+1234567890`).
|
||||
- Supports SMS, MMS, email, voice, fax, and postal mail.
|
||||
@@ -1,83 +0,0 @@
|
||||
---
|
||||
name: clickup
|
||||
version: "1.0.0"
|
||||
description: ClickUp API v2 — tasks, spaces, lists, comments, time tracking
|
||||
activation:
|
||||
keywords:
|
||||
- "clickup"
|
||||
- "clickup task"
|
||||
- "clickup space"
|
||||
exclude_keywords:
|
||||
- "jira"
|
||||
- "asana"
|
||||
patterns:
|
||||
- "(?i)clickup.*(task|space|list|folder)"
|
||||
- "(?i)(create|list|update).*clickup"
|
||||
tags:
|
||||
- "project-management"
|
||||
- "task-management"
|
||||
max_context_tokens: 1500
|
||||
metadata:
|
||||
openclaw:
|
||||
requires:
|
||||
env: [CLICKUP_API_TOKEN]
|
||||
---
|
||||
|
||||
# ClickUp API v2
|
||||
|
||||
Use the `http` tool. Credentials are automatically injected for `api.clickup.com`.
|
||||
|
||||
## Base URL
|
||||
|
||||
`https://api.clickup.com/api/v2`
|
||||
|
||||
## Actions
|
||||
|
||||
**List workspaces (teams):**
|
||||
```
|
||||
http(method="GET", url="https://api.clickup.com/api/v2/team")
|
||||
```
|
||||
|
||||
**List spaces:**
|
||||
```
|
||||
http(method="GET", url="https://api.clickup.com/api/v2/team/<team_id>/space")
|
||||
```
|
||||
|
||||
**List folders in space:**
|
||||
```
|
||||
http(method="GET", url="https://api.clickup.com/api/v2/space/<space_id>/folder")
|
||||
```
|
||||
|
||||
**List tasks in a list:**
|
||||
```
|
||||
http(method="GET", url="https://api.clickup.com/api/v2/list/<list_id>/task?page=0&subtasks=true&include_closed=false")
|
||||
```
|
||||
|
||||
**Get task:**
|
||||
```
|
||||
http(method="GET", url="https://api.clickup.com/api/v2/task/<task_id>")
|
||||
```
|
||||
|
||||
**Create task:**
|
||||
```
|
||||
http(method="POST", url="https://api.clickup.com/api/v2/list/<list_id>/task", body={"name": "Task name", "description": "Details", "status": "to do", "priority": 2, "due_date": 1775000000000, "assignees": [123456]})
|
||||
```
|
||||
|
||||
**Update task:**
|
||||
```
|
||||
http(method="PUT", url="https://api.clickup.com/api/v2/task/<task_id>", body={"status": "in progress", "priority": 1})
|
||||
```
|
||||
|
||||
**Add comment:**
|
||||
```
|
||||
http(method="POST", url="https://api.clickup.com/api/v2/task/<task_id>/comment", body={"comment_text": "My comment"})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Priority: 1=Urgent, 2=High, 3=Normal, 4=Low.
|
||||
- Due dates are Unix timestamps in **milliseconds**.
|
||||
- Status values are lowercase strings matching your workspace statuses.
|
||||
- Task IDs are alphanumeric strings like `"abc123"`.
|
||||
- Hierarchy: Team → Space → Folder → List → Task.
|
||||
- Pagination: `page` param (0-indexed). Returns empty array when no more.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user