For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /automations/troubleshooting-factory-runs.md.

Troubleshoot factory runs

Info

Takeaways:

  • Start from the issue or pull request. tessl launch list --link-type <its type> --link-value <its URL> finds every run it started, including runs that failed early.
  • No run linked means the event never reached a loop. Check delivery, the trigger's conditions, the loop, the environment, and credits, in that order.
  • A run that completed didn't necessarily succeed. Read its outcome: it can also be no_action or needs_input.
  • A passing connection check proves the configuration, not a run. Only a run linked to a real issue proves the factory works.

You labeled an issue, or delegated it to Tessl, and nothing happened. Or a run started and you can't tell what it did. This page walks each stage between the event and the pull request, with the check that tells you whether that stage is the problem and what to do next. For the terms loop, action, trigger, and run, see the Automations overview.

Find the run

Every run is linked to the issue or pull request whose event started it as soon as Tessl creates the run, so a run that failed before the agent started is still listed. List the runs for the item you're looking at:

# A GitHub issue
tessl launch list --link-type github_issue --link-value https://github.com/<owner>/<repo>/issues/<n> --limit 100 --json

# A pull request
tessl launch list --link-type github_pr --link-value https://github.com/<owner>/<repo>/pull/<n> --limit 100 --json

# A Linear issue
tessl launch list --link-type linear_issue --link-value <Linear issue URL> --limit 100 --json

Each run carries a webUrl that opens it in the browser. An empty list means no run started: go to When no run started. Otherwise, read the newest run with tessl launch view <id> and go to When a run started.

The runs that follow a pull request are linked to the pull request, not the issue. To get from an issue to its pull request, read the implementation run with tessl launch view <id> --json. The entry in data.attributes.links[] with rel set to produced is the pull request it opened. List that pull request's runs the same way.

When no run started

Work through these in order and stop at the first one that explains it.

The event is too recent

  • Check: how long ago you labeled, delegated, or commented. A run starts about 90 seconds after the event, and events close together fold into one run.
  • Next step: wait 2 minutes and list the runs again.

No event reached Tessl

  • Check: for a repo-defined loop, run tessl doctor --automations from the repository and read the Event delivery section. It covers only the triggers declared in the local tessl.json: for each one, it says whether that event, from this repository, reaches the workspace. A warning names the gap, such as the Tessl GitHub App not being installed on the repository, or an installation still waiting for the owner to accept it. When the file declares no triggers, the section doesn't appear, and that says nothing about delivery. For an app-defined loop, doctor doesn't check delivery: check the loop's triggers with tessl schedule view <loop id>, the GitHub App's access to the repository, and for Linear, Check loop connection in your organization's settings. Then look for the run itself, as Find the run describes.
  • Next step: fix the gap the warning or the configuration shows, then repeat the event. For Linear events, connect Linear to the organization and route the Linear team to the project, as Event triggers describes.

The event didn't match the trigger

  • Check: compare the event with the trigger's when conditions. For a repo-defined loop, they're in tessl.json. For an app-defined loop, they're in attributes.triggers of tessl schedule view <loop id> --json. The usual mismatches are a different label name, a sender the trigger doesn't accept (some triggers accept only listed GitHub user IDs, or ignore bots), an issue or pull request that's closed, and a pull request on a branch the trigger doesn't follow.
  • Next step: repeat the event so it matches, such as removing the label and adding the right one, or change the trigger's conditions.

The loop is paused or missing

  • Check: run tessl schedule list --project-id <project id> --all --json. Find the loop and read attributes.status. If no loop is listed for a trigger in tessl.json, read the Loops section of tessl doctor --automations: it says when the project hasn't processed a tessl.json yet, or has no event loop for the triggers the file declares.
  • Next step: resume a paused loop with tessl schedule resume <loop id>. For a missing repo-defined loop, merge tessl.json to the default branch, because loops come from the copy on the default branch, not the one on disk. See Stop, remove, and move loops.

The environment isn't bound to the project

  • Check: run tessl schedule view <loop id>. When a loop names an environment its runs can't use, the Environment line says why after the name, such as the project not being bound to it.
  • Next step: an organization admin binds the project with tessl environment bind <environment> --project <workspace>/<project>. See Bind projects to an environment.

The organization is out of credits

  • Check: run tessl org usage. It reads "Out of credits. Actions are paused." when runs can't start.
  • Next step: an organization admin adds credits. See Tessl Platform Pricing.

If none of these explains it, collect the output of tessl doctor --automations --json and the event's time in UTC, and give feedback to the Tessl team.

When a run started

tessl launch view <id> shows the run's Status and, once it has finished, its Outcome. The status combines what the platform recorded with what the agent reported, so read both before you decide what happened.

Still pending

  • Check: run tessl launch view <id> again a minute later. While a run works, Updated shows how recently it reported progress, about every 30 seconds. A run with no progress yet may be queued behind another run on the same issue or pull request.
  • Next step: follow it live with tessl launch logs <id> --watch. To stop it, run tessl launch cancel <id>. Cancellation is asynchronous: the run reads cancelled once it stops.

Error: preparation failed

tessl launch view shows error with an error code such as RECIPE_FAILED. That code alone doesn't say when the run failed: it also covers a run whose agent finished but wrote a result the run didn't accept. Read the preparation progress to tell them apart.

  • Check: run tessl launch progress <id> --filename prepare-subphases.json. When outcome is failed, preparation failed before the agent started: nothing reached your repository, and tessl launch logs has no transcript to show. first_failed names the step that failed, such as clone (getting the repository), cloud-launch-setup (your repository's setup hook), manifest-sync (syncing its configuration), or skill-install (installing the skill). tessl launch view <id> shows the error code, and for workspace admins, the failure details below it.
  • Next step: when outcome is ok, the preparation script passed, but that doesn't mean the agent ran: other setup tasks run after it and before the agent, such as registering MCP servers or starting Docker, and any of them can fail. Read the Failed tasks line and the failure details in tessl launch view <id>, and the transcript from tessl launch logs <id> if there is one. Go to Agent failed only when they show the agent started. For cloud-launch-setup, fix the hook as What happens when the hook fails describes. For any other step, check that the step's input exists: the repository and branch for clone, a tessl.json that tessl doctor --automations accepts for manifest-sync, and the skill's plugin for skill-install.

Agent failed

The agent started and stopped without finishing. tessl launch view shows agent failed with the reason the agent reported. A run that shows error and says it finished without the skill reporting a result belongs here too.

  • Check: read the reason, then the transcript: tessl launch logs <id> > run.log, and read the last messages and tool calls in the file. A run an event started has no way to wait for an answer, so when its agent needs one, it fails with the question as its reason.
  • Next step: when the reason is a question, answer it as Completed, waiting for your input describes. Otherwise, fix what the transcript shows, such as a failing test command or a missing credential in the environment. Then repeat the event that started the run.

Completed, waiting for your input

The run finished and its Outcome is needs_input: the agent asked a question only you can answer. A run an event started can't end this way: it reports its question as Agent failed. Either way, the question is a Tessl comment on the issue, and it says how to resume.

  • Check: read the latest Tessl comment on the issue.
  • Next step: answer it. On a Linear issue, answer in a comment and move the issue back to Todo. On a GitHub issue, reply on the issue, and your reply starts the next run. If no run starts a few minutes after you reply, remove the trigger label and add it again.

Completed with nothing to do

The Outcome is no_action. The agent looked and found nothing to change, such as a pull request with no new feedback.

  • Check: read the reason after the outcome in tessl launch view <id>, or the run's latest comment on the issue when it gives none.
  • Next step: none if the reason is right. If it isn't, add what's missing to the issue and repeat the event.

Completed and succeeded

The Outcome is succeeded: the agent finished its job. That job isn't always a pull request. An implementation run that found the issue blocked by another open issue also succeeds, after it comments on the issue to say so.

  • Check: run tessl launch view <id> --json and read data.attributes.links[]. A link with rel set to produced is what the run made, such as the pull request it opened. A run with only references links made nothing new: read its latest comment on the issue.
  • Next step: review the pull request. A pull request the factory opened is on a tessl/ branch of your repository and carries the tessl label. The loop that answers reviews and fixes checks follows only those pull requests, so a pull request opened by hand, or from a fork, gets no follow-up runs.

Canceled

  • Check: look on the issue for a note saying the run was stopped. The usual cause is a person taking the issue back, which the follow ticket changes loop acts on, or someone running tessl launch cancel.
  • Next step: to start again, repeat the event, or move a Linear issue back to Todo while it's still delegated to Tessl.

Connection checks aren't runs

The factory has 2 checks that say it is set up. Neither proves that it runs.

  • tessl doctor --automations validates the local tessl.json, the agent each action selects, the project's loops, and whether the events of each trigger the file declares reach the workspace. It doesn't check delivery for app-defined loops. It reads configuration and sends no event.
  • Check loop connection, on the Linear integration in your organization's settings, checks the Linear connection and how each team is routed to a project and its loops. It reads configuration only: it sends no issue to a loop and starts no run, and it reports webhook delivery and loop runs as not verified. The Linear connection isn't offered on the EU region.

A factory works when a real event starts a run you can find with tessl launch list --link-type <type> --link-value <URL>. After setup, or after any change to triggers, environments, or the setup hook, label or delegate one small issue and follow it through this page.