Skip to main content

Testing & Debugging DSL Bots

Authoring bots in .botgami offers major architectural safety. Instead of running scripts blind, the unified workspace runs static analysis, typechecking, and static mock simulations to detect errors before your code ever goes live.

This guide outlines the debugging tools built into the workspace, auditing conversational wait states, and best practices for clean bot engineering.


🐞 1. Pre-Deployment Static Verification

Botgami guards your runtime against failures through a two-tier verification layer:

Tier 1: In-Browser LSP Checking

As you type in the editor, a client-side Langium LSP Worker audits your document buffer:

  • Syntax Auditing: Identifies missing braces, missing block colons, or grammatical errors.
  • Type Checking: Validates that values assigned to variables match their declared schemas (e.g. attempting to push an object to a Number array).
  • Auto-Completions: Inspects step contracts to provide contextual autocomplete completions.

Tier 2: Server-Side Simulation Gate (simulate.Run)

When you save, the server runs a 14-stage compilation pipeline. The final gate is Static Simulation:

  • Mock Traversals: The compiler exercises all edges and branch pins in your DAG using mock stubs.
  • Diagnostics Blocking: If the simulation encounters an execution crash (such as passing the wrong number of arguments to a subflow call), it raises an Error level diagnostic and blocks the deployment. This ensures that syntactically correct but logically broken code cannot be deployed.

🔍 2. Debugging Techniques

Echo Debugging via Template Literals

When testing dynamic calculations or API payloads, you can "inspect" variables by outputting them to a temporary text message inside your flow:

flow check_state on command "/debug" {
send.text(
`🐞 **DEBUG CONTEXT**
──────────────────
user.points: ${user.points}
flow.category: ${flow.category}
ctx.Message.chat.id: ${ctx.Message.chat.id}
shared.leaderboard size: ${len(shared.leaderboard)}`,
parse_mode: "Markdown"
)
}

Auditing Session Wait States

If a user is stuck in a loop or not responding to buttons, they are likely paused on an active Wait State.

  • The DB Target: During interactive inputs (ask.text or menu_v2), the engine saves a record in the database under UserSession.CurrentNodeID.
  • The Reset Action: To clear a user's wait state manually during testing, send the /start command (provided your /start flow has a clear trigger that resets variables). Alternatively, you can use the admin dashboard's Reset Session toggle to wipe the user's active session state in Redis.

✨ 3. Best Practices for .botgami Codebases

A. Maintain DRY via Reusable Subflows

If you copy and paste more than two send or ask statements, extract them into a subflow subroutine:

// ❌ BAD: Chaining duplicate ask logic
flow ask_details on command "/signup" {
name = ask.text("Name:")
when name == "" { ... }
email = ask.text("Email:")
when email == "" { ... }
}

// ✅ GOOD: Abstract into a subflow
subflow collect_input(prompt: String) -> { reply: String } {
reply = ask.text(prompt)
when trim(reply) == "" {
send.text("Input cannot be empty!")
fail { msg: "Empty input" }
}
return { reply: reply }
}

B. Enforce HTTP Error Failsafes

Never call an external API without wrapping the call in a robust .onError handler.

  • If the external API is down, a missing handler will halt the execution flow silently, leaving the user with a frozen spinner.
  • Always alert the user and call stop to exit safely:
result = http.get("https://api.example.com").onError {
send.text("Service temporarily unavailable. Please try again later. ⚠️")
stop
}

C. Leverage the when Reserved Keyword Rule

Avoid declaring variable or object fields named when to prevent parser collisions. Use descriptive names like event_time, date, or trigger_schedule.


Next Steps