Convert executed workflow into a reusable notebook. Only use when workflow is complete or user explicitly requests. --- DESCRIPTION FORMAT (MARKDOWN) - MUST BE NEUTRAL --- Description is for ANY user of this recipe, not just the creator. Keep it generic. - NO PII (no real emails, names, channel n...
Risk signalsBulk/mass operation — affects multiple targets
Part of the Rube server.
Free to start. No card required.
AI agents use RUBE_CREATE_UPDATE_RECIPE to create or modify resources in Rube. Write operations carry medium risk because an autonomous agent could trigger bulk unintended modifications. Rate limits prevent a single agent session from making hundreds of changes in rapid succession. Argument validation ensures the agent passes expected values.
Without a policy, an AI agent could call RUBE_CREATE_UPDATE_RECIPE repeatedly, creating or modifying resources faster than any human could review. PolicyLayer's rate limiting ensures write operations happen at a controlled pace, and argument validation catches malformed or unexpected inputs before they reach Rube.
Write tools can modify data. A rate limit prevents runaway bulk operations from AI agents.
{
"version": "1",
"default": "deny",
"tools": {
"RUBE_CREATE_UPDATE_RECIPE": {
"limits": [
{
"counter": "rube_create_update_recipe_rate",
"window": "minute",
"max": 30,
"scope": "grant"
}
]
}
}
} See the full Rube policy for all 11 tools.
These attack patterns abuse exactly the kind of access RUBE_CREATE_UPDATE_RECIPE gives an agent. Each links to the full case and the policy that stops it:
Other write tools across the catalogue. The same approach applies to each: rate-limit and validate the arguments.
Convert executed workflow into a reusable notebook. Only use when workflow is complete or user explicitly requests. --- DESCRIPTION FORMAT (MARKDOWN) - MUST BE NEUTRAL --- Description is for ANY user of this recipe, not just the creator. Keep it generic. - NO PII (no real emails, names, channel names, repo names) - NO user-specific defaults (defaults go in defaults_for_required_parameters only) - Use placeholder examples only Generate rich markdown with these sections: Overview [2-3 sentences: what it does, what problem it solves] How It Works [End-to-end flow in plain language] Key Features - [Feature 1] - [Feature 2] Step-by-Step Flow 1. [Step]: [What happens] 2. [Step]: [What happens] Apps & Integrations | App | Purpose | |-----|---------| | [App] | [Usage] | Inputs Required | Input | Description | Format | |-------|-------------|--------| | channel_name | Slack channel to post to | WITHOUT # prefix | (No default values here - just format guidance) Output [What the recipe produces] Notes & Limitations - [Edge cases, rate limits, caveats] --- CODE STRUCTURE --- Code has 2 parts: 1. DOCSTRING HEADER (comments) - context, learnings, version history 2. EXECUTABLE CODE - clean Python that runs DOCSTRING HEADER (preserve all history when updating): """ RECIPE: [Name] FLOW: [App1] → [App2] → [Output] VERSION HISTORY: v2 (current): [What changed] - [Why] v1: Initial version API LEARNINGS: - [API_NAME]: [Quirk, e.g., Response nested at data.data] KNOWN ISSUES: - [Issue and fix] """ Then EXECUTABLE CODE follows (keep code clean, learnings stay in docstring). --- INPUT SCHEMA (USER-FRIENDLY) --- Ask for: channel_name, repo_name, sheet_url, email_address Never ask for: channel_id, spreadsheet_id, user_id (resolve in code) Never ask for large inputs: use invoke_llm to generate content in code GOOD DESCRIPTIONS (explicit format, generic examples - no PII): channel_name: Slack channel WITHOUT # prefix repo_name: Repository name only, NOT owner/repo google_sheet_url: Full URL from browser gmail_label: Label as shown in Gmail sidebar REQUIRED vs OPTIONAL: - Required: things that change every run (channel name, date range, search terms) - Optional: generic settings with sensible defaults (sheet tab, row limits) --- DEFAULTS FOR REQUIRED PARAMETERS --- - Provide in defaults_for_required_parameters for all required inputs - Use values from workflow context - Use empty string if no value available - never hallucinate - Match types: string param needs string default, number needs number - Defaults are private to creator, not shared when recipe is published - SCHEDULE-FRIENDLY DEFAULTS: - Use RELATIVE time references unless user asks otherwise, not absolute dates ✓ "last_24_hours", "past_week", "7" (days back) ✗ "2025-01-15", "December 18, 2025" - - Never include timezone as an input parameter unless specifically asked - - Test: "Will this default work if recipe runs tomorrow?" --- CODING RULES --- SINGLE EXECUTION: Generate complete notebook that runs in one invocation. CODE CORRECTNESS: Must be syntactically and semantically correct and executable. ENVIRONMENT VARIABLES: All inputs via os.environ.get(). Code is shared - no PII. TIMEOUT: 4 min hard limit. Use ThreadPoolExecutor for bulk operations. SCHEMA SAFETY: Never assume API response schema. Use invoke_llm to parse unknown responses. NESTED DATA: APIs often double-nest. Always extract properly before using. ID RESOLUTION: Convert names to IDs in code using FIND/SEARCH tools. FAIL LOUDLY: Raise Exception if expected data is empty. Never silently continue. CONTENT GENERATION: Never hardcode text. Use invoke_llm() for generated content. DEBUGGING: Timestamp all print statements. NO META LOOPS: Never call RUBE_* or RUBE_* meta tools via run_composio_tool. OUTPUT: End with just output variable (no print). --- HELPERS --- Available in notebook (dont import). See RUBE_REMOTE_WORKBENCH for details: run_composio_tool(slug, args) returns (result, error) invoke_llm(prompt, reasoning_effort="low") returns (response, error) # reasoning_effort: "low" (bulk classification), "medium" (summarization), "high" (creative/complex content) # Always specify based on task - use low by default, medium for analysis, high for creative generation proxy_execute(method, endpoint, toolkit, ...) returns (result, error) upload_local_file(*paths) returns (result, error) --- CHECKLIST --- - Description: Neutral, no PII, no defaults - for any user - Docstring header: Version history, API learnings (preserve on update) - Input schema: Human-friendly names, format guidance, no large inputs - Defaults: In defaults_for_required_parameters, type-matched, from context - Code: Single execution, os.environ.get(), no PII, fail loudly - Output: Ends with just output. It is categorised as a Write tool in the Rube MCP Server, which means it can create or modify data. Consider rate limits to prevent runaway writes.
Register the Rube MCP server in PolicyLayer and add a rule for RUBE_CREATE_UPDATE_RECIPE: allow, deny, rate-limit, or require approval. Point your MCP client at the PolicyLayer proxy URL and the rule is enforced on every call, before it reaches Rube. Nothing to install.
RUBE_CREATE_UPDATE_RECIPE is a Write tool with medium risk. Write tools should be rate-limited to prevent accidental bulk modifications.
Yes. Add a rate_limit block to the RUBE_CREATE_UPDATE_RECIPE rule in your PolicyLayer policy. For example, setting max: 10 and window: 60 limits the tool to 10 calls per minute. Rate limits are tracked per agent session and reset automatically.
Set action: deny in the PolicyLayer policy for RUBE_CREATE_UPDATE_RECIPE. The AI agent will receive a policy violation error and cannot call the tool. You can also include a reason field to explain why the tool is blocked.
RUBE_CREATE_UPDATE_RECIPE is provided by the Rube MCP server (Composio/Rube). PolicyLayer sits as a proxy in front of this server to enforce policies before tool calls reach the server.
Deterministic rules across all 11 Rube tools. Per-identity grants. Full audit log. Live in minutes. Nothing to install.
Free to start. No card required.
4,600+ MCP servers and 31,000+ tools scanned and risk-classified.