Skip to main content
Action tracing provides comprehensive visibility into your automation workflows through two complementary features: detailed step logging and visual GIF recording.

Action Trace Response

Action traces provide detailed step-by-step logs of automation execution, returned in API responses for both custom agent shortcuts and /Operator commands.

Operator Traces

Simple action logs for /Operator commands:
{
  "actionTrace": [
    {
      "url": "https://arxiv.org/",
      "action": "Typed 'artificial intelligence' and pressed Enter into search input"
    },
    {
      "url": "https://arxiv.org/search/",
      "action": "Clicked on search button"
    }
  ]
}

Custom Agent Traces

Detailed step logs for custom agent workflows with multiple action types:
{
  "actionTrace": [
    {
      "url": "https://example.com",
      "step_type": "goToUrl",
      "description": "Navigated to https://example.com"
    },
    {
      "url": "https://example.com",
      "step_type": "agent",
      "agent_type": "operator",
      "action_trace": [...]
    }
  ]
}

Supported Step Types

Custom agent traces use a step_type field to identify the action. The full list of supported step types:
Step TypeDescription
start / endWorkflow boundaries
goToUrlNavigate to a URL
getUrlGet the current page URL
agentSub-agent invocation (contains nested action_trace)
agenticSelectorElement selection via CSS selectors with fallback
agenticMouseActionMouse action at recorded coordinates
getFullHtml / getSimplifiedHtmlHTML content capture
getScreenshotScreenshot capture
printPrint a message to the chat
pythonInline Python code execution
for / whileLoop constructs
ifConditional branching
setVariableVariable assignment
waitDelay step
waitForElementWait for an element to appear
pressKeysKeyboard input
readGoogleSheet / writeGoogleSheetGoogle Sheets operations
dataTableExportAsCsvExport data as CSV
objectExportAsJsonExport data as JSON
dataTableInsertRow / dataTableUpdateCellValueData table operations
objectSetPropertiesObject property updates
runCustomAgentInvoke another custom agent workflow

Formatting Example

Convert action traces to readable markdown (handles multiple custom agent step types):
def format_action_trace(trace_data):
    if not trace_data:
        return "No action trace available"

    markdown = "# Action Trace\n\n"

    for i, step in enumerate(trace_data, 1):
        if 'action' in step:
            # Operator trace
            markdown += f"{i}. **{step['url']}**\n   - {step['action']}\n\n"
        else:
            # Custom agent trace - handle different step types
            step_type = step['step_type']
            description = step.get('description', step_type)

            if step_type == 'goToUrl':
                markdown += f"{i}. 🌐 **Navigate** to {step.get('url', 'URL')}\n"
            elif step_type == 'agent':
                agent_type = step.get('agent_type', 'unknown')
                markdown += f"{i}. πŸ€– **Agent** ({agent_type}) - {description}\n"
                if step.get('action_trace'):
                    markdown += f"   - Contains {len(step['action_trace'])} sub-actions\n"
            elif step_type in ['for', 'while']:
                markdown += f"{i}. πŸ”„ **Loop** ({step_type}) - {description}\n"
            elif step_type == 'python':
                markdown += f"{i}. 🐍 **Code Execution** - {description}\n"
            elif step_type == 'print':
                markdown += f"{i}. πŸ“ **Message** - {description}\n"
            elif step_type == 'agenticSelector':
                markdown += f"{i}. 🎯 **Element Selection** - {description}\n"
            elif step_type == 'agenticMouseAction':
                markdown += f"{i}. πŸ–±οΈ **Mouse Action** - {description}\n"
            else:
                markdown += f"{i}. ⚑ **{step_type.title()}** - {description}\n"

            markdown += "\n"

    return markdown

GIF Recording

import asyncio
from narada import Narada

async def main() -> None:
    async with Narada() as narada:
        window = await narada.open_and_initialize_browser_window()

        # Run automation with GIF recording enabled
        response = await window.agent(
            prompt='search for "machine learning" on Google and extract the number of results',
            generate_gif=True  # Enable GIF recording
        )

        print("Response:", response.output.content)
        print("GIF saved to your Downloads/Narada Downloads folder!")

if __name__ == "__main__":
    asyncio.run(main())
The SDK automatically compiles frames into an animated GIF showing the complete automation trajectory.
1

Automatic Directory Creation

Narada automatically creates a directory structure for your GIFs:
  1. Main Directory: Narada Downloads in your machine’s Downloads folder
  2. Request Directory: Directory named after your request_id from the SDK response
  3. File: Automation saved as an animated .gif file
If the Narada Downloads directory doesn’t exist, it will be created automatically.
2

Find Your GIF File

Navigate to your Downloads folder and look for:
Downloads/
└── Narada Downloads/
    └── req_abc123def456/
        └── automation_recording.gif
Each GIF request gets its own directory named after the request_id for easy correlation with your SDK calls.

Best Practices

Debugging

Use action traces for programmatic debugging and GIFs for visual verification

Auditing

Action traces provide detailed audit logs for compliance and monitoring

Documentation

GIFs document visual workflows while action traces capture step-by-step logic

Analysis

Parse action traces to analyze automation patterns and optimize workflows