Skip to main content
RbxGenie imposes strict guidelines to prevent tool overuse, reduce token costs, and improve performance. Follow these rules when building AI agents.

Core Principle: Think Before You Call

DO NOT OVERUSE TOOLS. You are strictly penalized for unnecessary tool calls. Read code and think instead of using trial-and-error.

Anti-Tool Overuse Rules

1. NO BLIND EXPLORATION

Call summarize_game ONCE per session if you have no prior context. Do NOT call it again if you already have the result in context. NEVER call get_file_tree or get_project_structure without a scoped path:
// BAD: Returns entire game tree (expensive)
{ "path": "game" }

// GOOD: Scoped to specific service with depth limit
{ "path": "StarterGui", "depth": 2 }

2. NO RE-FETCHING

If you already fetched a file or tree, rely on your context memory. Do not call info tools twice for the same data.
// BAD
get_script_source({ "path": "ServerScriptService.MyScript" })
// ... do some work ...
get_script_source({ "path": "ServerScriptService.MyScript" })  // Duplicate!

// GOOD
get_script_source({ "path": "ServerScriptService.MyScript" })
// Use the result from context

3. NO TRIAL-AND-ERROR

Do not spam execute_luau or run_script_in_play_mode to guess how things work. Use get_script_source to read the code and figure it out.

4. USE BULK TOOLS

Always use bulk operations instead of multiple individual calls:
  • mass_set_property instead of multiple set_property
  • mass_create_objects instead of multiple create_object
  • mass_duplicate instead of multiple smart_duplicate
  • mass_get_property instead of multiple property queries
Example:
// BAD: 3 tool calls, 3 HTTP requests, 3 undo waypoints
set_property({ "path": "Workspace.A", "property": "Anchored", "value": true })
set_property({ "path": "Workspace.B", "property": "Anchored", "value": true })
set_property({ "path": "Workspace.C", "property": "Anchored", "value": true })

// GOOD: 1 tool call, 1 HTTP request, 1 undo waypoint
mass_set_property({
  "paths": ["Workspace.A", "Workspace.B", "Workspace.C"],
  "property": "Anchored",
  "value": true
})

Scoping Rules

Always scope search and query operations:
ToolRule
get_file_treeAlways set "path" to a specific service; never "path": "game" without "depth": 1
get_instance_childrenOnly "recursive": true with narrow path; max 200 results
search_files / search_objectsAlways supply "path"
search_by_propertyAlways supply "path" and "className"
Example:
// BAD: Searches entire game
{ "query": "Button" }

// GOOD: Scoped to StarterGui
{ "query": "Button", "path": "StarterGui" }

// BETTER: Even more specific
{ "query": "Button", "path": "StarterGui.MyGui", "className": "TextButton" }

Playtesting Guidelines

Playtesting is EXPENSIVE and PRONE TO FREEZING. Do NOT playtest unless absolutely necessary.

Only Playtest When:

  1. Building something from scratch — a new system, feature, or major component.
  2. Making a large/complex change that affects runtime behavior across multiple scripts.
  3. You keep hitting errors and cannot figure out the root cause from code inspection alone.

Do NOT Playtest When:

  • Changing a single property, renaming, or tweaking values.
  • Editing a few lines of a script.
  • The change is purely structural (reparenting, reorganizing).
  • You are confident the change is correct from reading the code.

Anti-Freeze Protocol

ALWAYS specify a low timeout parameter (e.g., 30 seconds) when using run_script_in_play_mode:
{
  "code": "print('test') return 42",
  "timeout": 30,
  "mode": "play"
}

Token Cost Optimization

Minimize Context Usage

  1. Read only what you need: Don’t fetch entire scripts if you only need to check a few lines.
  2. Use line ranges: edit_script_lines with precise startLine/endLine instead of rewriting entire scripts.
  3. Batch operations: Combine multiple related changes into a single bulk call.

Efficient Code Reading

// Get script source once
get_script_source({ "path": "ServerScriptService.MyScript" })

// Edit specific lines
edit_script_lines({
  "path": "ServerScriptService.MyScript",
  "startLine": 10,
  "endLine": 15,
  "replacement": "-- updated code\nprint('new')"
})

// NOT: get_script_source → set_script_source (full rewrite)

Prefer Calculated Properties

Use set_calculated_property for mathematical transformations:
// GOOD: Read once, calculate, set once
set_calculated_property({
  "path": "Workspace.Part",
  "property": "Size",
  "expression": "current * 2"
})

// BAD: Read, calculate in agent, set
mass_get_property({ "paths": ["Workspace.Part"], "property": "Size" })
// ... calculate in agent context ...
set_property({ "path": "Workspace.Part", "property": "Size", "value": {...} })

Tool Call Limits

Absolute Maximums

  • get_file_tree: Max 200 instances returned
  • get_instance_children (recursive): Max 200 instances returned
  • search_files / search_objects: Max 50 results
  • execute_luau / run_script_in_play_mode: 120s timeout (override with lower value)
  • mass_set_property: Up to 100 paths per call
  • mass_create_objects: Up to 50 objects per call
  • mass_duplicate: Up to 50 instances per call
If you need to operate on more instances, split into multiple batched calls.

Keep It Simple — No Overengineering

Do NOT overengineer. Deliver exactly what was asked — nothing more.
  • If the request is simple, the solution must be simple.
  • Do not add extra abstractions, helper modules, config layers, or “future-proof” patterns unless explicitly requested.
  • Do not refactor surrounding code that wasn’t part of the request.
  • Do not create unnecessary wrapper functions or utility modules.
  • Fewer lines is better. Ship the minimal correct solution.
Example: User Request: “Make all parts in Workspace transparent”
// GOOD: Direct solution
search_objects({ "className": "Part", "path": "Workspace" })
// Get paths from results
mass_set_property({
  "paths": [...],
  "property": "Transparency",
  "value": 1
})
BAD: Creating a “TransparencyManager” module, adding configuration files, implementing undo tracking systems, etc.

Summary Checklist

Before calling a tool, ask:
  • ✅ Have I already called this tool with the same arguments?
  • ✅ Can I use a bulk operation instead of multiple individual calls?
  • ✅ Have I scoped the operation with a specific path?
  • ✅ Am I using the minimum depth/limit necessary?
  • ✅ Can I read code instead of executing trial-and-error?
  • ✅ Do I really need to playtest this change?
  • ✅ Is this the simplest solution to the user’s request?
If you can’t answer “yes” to these questions, reconsider your approach.

Build docs developers (and LLMs) love