Composio abstracts away tool internals -- great for getting started, painful when something goes wrong. Here is how to debug it.

The Black Box Problem

Composio's core value proposition is giving AI agents access to 250+ pre-built tool integrations without writing OAuth flows or API clients. The trade-off: you cannot inspect or modify the underlying tool code. When a tool call returns an unexpected result -- or no result -- diagnosing the problem requires knowing where to look.

This article covers the debugging toolkit for Composio tool calls.

Enabling Verbose Logging

The first thing to add when debugging any Composio tool issue: verbose logging. This shows every tool call, its parameters, and the raw response from the external API.

import logging
from composio_langchain import ComposioToolSet
 
# Enable debug logging before creating the toolset
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("composio").setLevel(logging.DEBUG)
 
toolset = ComposioToolSet(api_key="your-api-key")
tools = toolset.get_tools(actions=["GMAIL_SEND_EMAIL", "SLACK_SEND_MESSAGE"])
 
# Now run your agent -- every tool call will be logged with full details

Executing Tools Directly

The fastest debugging technique: call the Composio tool directly without an LLM agent. This isolates the tool itself from any agent or LLM decision-making issues.

from composio_langchain import ComposioToolSet, Action
 
toolset = ComposioToolSet(api_key="your-api-key")
 
# Execute a tool directly with known inputs
result = toolset.execute_action(
    action=Action.GMAIL_SEND_EMAIL,
    params={
        "recipient_email": "test@example.com",
        "subject": "Test from Composio debug",
        "body": "This is a direct tool execution test.",
    },
    # Use a specific connected account if you have multiple
    connected_account_id="your-connected-account-id",
)
 
print("Tool execution result:")
print(result)
If the direct execution works but the agent call does not, the problem is in the LLM's tool selection or parameter generation -- not the tool itself. If direct execution also fails, the problem is authentication, API limits, or tool configuration.

Checking Connected Account Status

A large proportion of Composio tool failures are authentication failures -- the connected account's token has expired or been revoked. Check account status before assuming the tool itself is broken.

from composio import Composio
 
client = Composio(api_key="your-api-key")
 
# List all connected accounts
accounts = client.connected_accounts.get()
for account in accounts:
    print(f"App: {account.appName}")
    print(f"Status: {account.status}")   # 'ACTIVE', 'EXPIRED', 'FAILED'
    print(f"Account ID: {account.id}")
    print()
 
# Check a specific account
account = client.connected_accounts.get(connected_account_id="your-account-id")
if account.status != "ACTIVE":
    print(f"Account is not active: {account.status}")
    print("User needs to re-authenticate via the Composio connect flow")

MCP Tool Call Latency

When using Composio via MCP (Model Context Protocol), each tool call is an external HTTP request to Composio's servers. For agents that make multiple sequential tool calls, latency compounds. A 5-step agent task with 500ms per tool call adds 2.5 seconds of pure tool latency.

Diagnosing MCP latency

import time
from composio_langchain import ComposioToolSet, Action
 
toolset = ComposioToolSet(api_key="your-api-key")
 
# Measure tool execution time
start = time.time()
result = toolset.execute_action(
    action=Action.GITHUB_LIST_REPOSITORIES,
    params={"username": "your-org"},
)
elapsed = time.time() - start
print(f"Tool execution took: {elapsed:.3f}s")
 
# If regularly >1s: check your network to Composio's servers
# If regularly 200-500ms: normal for external API calls
# If regularly <100ms: cached or fast API

Reducing compound latency

  • Identify which tools are called most frequently and test their individual latency
  • For tools with consistently high latency, consider caching their results in your application when the data is unlikely to change within a session
  • Structure agent prompts to minimise the number of tool calls needed -- an agent that retrieves all needed data in 2 calls is faster than one that makes 5 calls

Tool Parameter Errors

LLMs sometimes generate tool call parameters that fail Composio's validation. The error messages are not always clear. Common patterns:

# Pattern: catch and log tool execution errors explicitly
from composio_langchain import ComposioToolSet
from langchain.agents import AgentExecutor
 
def handle_tool_error(error: Exception) -> str:
    """Custom error handler for tool failures."""
    error_msg = str(error)
    print(f"Tool error: {error_msg}")
 
    # Common Composio error patterns
    if "401" in error_msg or "Unauthorized" in error_msg:
        return "Authentication failed. The connected account may need to be re-authorised."
    if "422" in error_msg or "validation" in error_msg.lower():
        return f"Invalid parameters provided to the tool: {error_msg}"
    if "429" in error_msg or "rate limit" in error_msg.lower():
        return "Rate limit reached for this API. Please wait before retrying."
    return f"Tool execution failed: {error_msg}"
 
# Add to your LangChain agent
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    handle_parsing_errors=True,
    handle_tool_errors=handle_tool_error,  # custom handler
    verbose=True,
)

Quick Reference

  • Enable logging.getLogger('composio').setLevel(logging.DEBUG) first
  • Use toolset.execute_action() to test tools directly without an LLM
  • Check connected account status (ACTIVE/EXPIRED/FAILED) before assuming tool bugs
  • Measure tool latency individually -- MCP calls compound across sequential tool use
  • Add a custom handle_tool_errors handler to surface actionable error messages to the agent