Skip to content

Latest commit

 

History

History
319 lines (241 loc) · 11.7 KB

troubleshooting.md

File metadata and controls

319 lines (241 loc) · 11.7 KB

CALL-E Troubleshooting

Which standalone Skill is installed?

The canonical standalone MCP/API Skill is calle 1.0.2. Verify its loaded name and version after host reload, not just its directory on disk. Plugin-owned calle entries have separate lifecycles; identify the intended standalone or plugin entry when the host exposes overlapping names.

The legacy CLI compatibility entry is calle-cli; its executable remains calle, and authentication and recovery state stay on the original CLI path. Users retaining the old standalone CLI workflow should follow the explicit migration steps. Do not fix a name mismatch by logging out, deleting credentials or recreating a pending call.

The temporary callev2 testing source is retired, and migration of its installed copies is outside this release's scope. Same-name update checks do not authorize switching Skill identity or publisher. An unavailable source means unknown update status.

Use this guide when CALL-E installation, authentication, or tool verification fails in a local agent environment.

Cursor agent shell returns CONNECT tunnel failed, response 403

Symptoms

A request works in your terminal but fails in the Cursor agent shell with CONNECT tunnel failed, response 403. The CALL-E CLI may also report fetch failed.

Check the sandbox

In Cursor 3.21.16, the setting is under Settings → Agents → Execution and Approvals → Run Mode. Keep Auto-Review (with Sandbox) enabled while checking network access. Run this in the agent shell:

printf "CURSOR_SANDBOX=%s\n" "$CURSOR_SANDBOX"
curl -sS --connect-timeout 10 --max-time 20 -o /dev/null -w "HTTP %{http_code}\n" https://seleven-mcp-sg.airudder.com/

On macOS, CURSOR_SANDBOX=seatbelt identifies the sandbox. If curl reports a CONNECT 403 there but reaches the same host in your terminal, check the sandbox's domain policy. A generic fetch failed alone does not identify the cause.

Allow the CALL-E host

Using your editor, add the CALL-E host to the workspace's .cursor/sandbox.json. If the file already exists, merge the entry into its networkPolicy.allow list without replacing other settings:

{
  "networkPolicy": {
    "default": "deny",
    "allow": ["seleven-mcp-sg.airudder.com"]
  }
}

This keeps the sandbox enabled. Existing deny rules and organization policies can still block the host; see Cursor's sandbox configuration reference. Retry the curl check. An HTTP 404 from this root URL still confirms that HTTPS reached the server; it does not verify authentication.

Verify the CLI through the sandbox proxy

If curl connects but the Node CLI still reports fetch failed, Node may not be using the sandbox's proxy. Follow CLI entry point selection to prepare the trusted launcher and a tools-request.json with this argv:

["mcp", "tools"]

With an existing CALL-E login, run:

NODE_USE_ENV_PROXY=1 node run-agent-command.mjs tools-request.json

This asks Node to use the proxy environment supplied by the sandbox. Keep TLS certificate verification enabled. The environment variable requires a Node version that supports it; see the Node reference. A successful response has ok: true and lists plan_call, run_call, and get_call_run among its tools.

These steps were tested on macOS with Cursor 3.21.16, Node 26.8.2, and CALL-E CLI 0.5.2, using an existing login. The domain entry resolved curl's CONNECT 403; NODE_USE_ENV_PROXY=1 also resolved the CLI's fetch failed. This check does not cover a fresh OAuth login or skill installation.

Run CALL-E from Python on Windows

For Python applications, invoke the existing CLI launcher with a trusted Node executable and pass arguments as JSON through stdin. This avoids Windows command-name lookup and shell parsing of argument values. The launcher verifies that the selected package is @call-e/cli before running it.

Recommended invocation

Follow CLI entry point selection to select a trusted installation. Replace the two paths below with your absolute Node executable and @call-e/cli package paths:

import json
import subprocess
from pathlib import Path

node = Path(r"C:\Program Files\nodejs\node.exe")
package_dir = Path(r"C:\trusted\node_modules\@call-e\cli")
launcher = package_dir / "scripts" / "run-agent-command.mjs"
request = {"package_dir": str(package_dir), "argv": ["--help"]}

subprocess.run(
    [str(node), str(launcher)],
    input=json.dumps(request),
    text=True,
    shell=False,
    check=True,
)

This help check requires no login and makes no calls. Use the same invocation on macOS or Linux with the corresponding absolute paths. For other commands, change argv; see the CLI reference for integration attribution and returned argument arrays.

Common questions

Why does calle work in my terminal but fail from Python?

Python's subprocess.run(["calle", "--help"]) can raise FileNotFoundError: [WinError 2] on Windows. npm provides a calle.cmd wrapper, while a direct process launch does not resolve the bare name like a shell does. The CLI has not started when this error occurs.

Can I use calle.cmd or cmd /c instead?

The reported Windows test confirmed that calle.cmd --help displayed help when called from Python, and the reporter used cmd /c for a status query. Those results do not verify arbitrary arguments. For application integrations, use the recommended launcher: command scripts can reinterpret quotes, special characters, and multiline text. Adding shell=True is not needed.

Where do I find the paths?

In PowerShell, Get-Command node.exe shows the Node executable. For a global npm installation, npm root -g gives the package root; append @call-e/cli to that directory. For a local installation, select the trusted application's node_modules/@call-e/cli directory. Configure these paths once instead of running discovery commands before every invocation.

How do I pass spaces, quotes, or multiline text?

Keep each argument as one string in argv, including an entire multiline value as one element. Let json.dumps serialize the request. Do not add shell quotes to individual arguments, concatenate a command string, or use shell=True.

What if the launcher rejects the package or entry point?

Check that package_dir names the @call-e/cli directory, not its parent node_modules directory or the older @call-e/calle SDK. If the launcher reports that command-help checks failed, update the trusted CLI installation as directed by the CLI reference before authenticating.

Run CALL-E from Node on Windows

Symptoms

A Node integration on Windows may abort while its host process exits with this libuv assertion:

Assertion failed: !(handle->flags & UV_HANDLE_CLOSING), file src\win\async.c, line 94

This has been observed when the same long-running Node process starts CALL-E with asynchronous spawn() handles and also uses a synchronous child process, such as execSync("npm root -g"), to discover the CLI entry point.

A separate shell-launch symptom can occur when a multiline --goal is sent through cmd /c: cmd.exe may split or reinterpret the arguments before the CLI receives them, sometimes surfacing as Unknown option: --to-phone.

Cause

In the reported configuration, the assertion came from Node/libuv teardown in the embedding process after synchronous and asynchronous child-process paths were mixed. It is not evidence that the CALL-E CLI rejected the request or failed internally. The same assertion can have other causes, so apply this guidance when the host matches the child-process pattern above.

The multiline failure is related but distinct: a command shell parses the command string before CALL-E sees it, so newlines and quoting may change the argument boundaries.

Fix

Keep the embedded CLI launch asynchronous and shell-free from discovery through process exit:

  1. Install @call-e/cli as a dependency of the embedding application and resolve its published JavaScript entry point during application startup.
  2. Start that entry point with the current Node executable and asynchronous spawn().
  3. Pass every CLI token as a separate array element, including the complete multiline goal as one element.
  4. Set shell: false and wait for the child process to close before tearing down the host.
import { spawn } from "node:child_process";
import { once } from "node:events";
import { createRequire } from "node:module";

const require = createRequire(import.meta.url);
const cliEntry = require.resolve("@call-e/cli/bin/calle.js");

export async function planCall({ phone, goal }) {
  const child = spawn(
    process.execPath,
    [
      cliEntry,
      "call",
      "plan",
      "--to-phone",
      phone,
      "--goal",
      goal,
    ],
    {
      shell: false,
      stdio: "inherit",
      windowsHide: true,
    },
  );

  const [exitCode] = await once(child, "close");
  if (exitCode !== 0) {
    throw new Error(`calle call plan exited with code ${exitCode}`);
  }
}

Do not route this integration path through cmd /c, a PowerShell command string, or a package-manager command shim. Do not run execSync("npm root -g") while the host still owns live asynchronous child handles. If a global CLI install is unavoidable, resolve its absolute entry path outside the long-running host, inject it as application configuration, and validate it before starting concurrent child work.

Verify

First use the same launch pattern with call plan --help; this verifies the shell-free child path and normal process exit without a network request. Then use calle call plan with a multiline goal; planning does not place a call. Confirm that the integration no longer reports shell argument-parsing errors and that the child and host processes exit normally. If the assertion remains in an integration that does not match the pattern above, investigate that host's other child handles and teardown paths separately.

calle call plan fails with MCP request timed out for tools/call

Symptoms

calle call plan exits with this error while authentication and MCP tool discovery still work:

MCP request timed out for tools/call

Cause

The plan_call request took longer than the CLI's effective request timeout. Current CLI releases allow 150 seconds for plan_call by default while keeping the shared 15-second default for other MCP requests. Older CLI releases used the shared 15-second timeout for planning too. An explicit --timeout-seconds value overrides either default.

This is a client-side timeout, not an authentication error. Planning does not place a call, so it is safe to retry after adjusting the timeout.

Fix

Check the defaults reported by the installed CLI:

["call", "plan", "--help"]

If the command used an explicit timeout shorter than planning needs, remove the flag to use the current planning default or retry with a longer value:

["call", "plan", "--to-phone", "+15551234567", "--goal", "Confirm the appointment", "--timeout-seconds", "300"]

If help reports only the 15-second shared default for planning, update the CLI and retry:

npm install -g @call-e/cli

See the CLI reference for the canonical timeout defaults and option behavior.

Verify

A successful retry prints the planned call payload as JSON. Review the plan and continue through the normal confirmation flow; do not treat a successful plan as evidence that a call has already started.