← Back to skills

Domain skill

tasksquad-ai

Markdown synced from browser-harness domain skills.

Host
tasksquad-ai
Files
3

Agent prompt

Use this skill

Copy this prompt into your coding agent to make it enable browser-harness domain skills and read this exact domain folder before automating.

Set up https://github.com/browser-use/browser-harness for me if it is not already installed. If setup is needed, read `install.md` first to install and connect it to my real browser. Then read `SKILL.md` for normal usage and always read `helpers.py` because that is where the browser-harness functions are.

Enable domain skills if they are not already enabled by setting `BH_DOMAIN_SKILLS=1` for browser-harness. Use the `tasksquad-ai` domain skill from `agent-workspace/domain-skills/tasksquad-ai/`. Read every markdown file for this domain before inventing an approach:
- agent-workspace/domain-skills/tasksquad-ai/agents.md
- agent-workspace/domain-skills/tasksquad-ai/auth.md
- agent-workspace/domain-skills/tasksquad-ai/tasks.md

Use those domain-skill notes to complete my task for `tasksquad-ai` in my real browser. When you open a setup, verification, or task tab, activate it so I can see the active browser tab.

Skill contents

What the agent will read

Agents

agents.md

Source
  • Field-tested against tasksquad.ai on 2026-05-03 using a logged-in Chrome session.
  • Agents are the daemon workers that execute tasks. Each agent card shows:
  • Name
  • Status badge (active / inactive / running / waitinginput / paused)
Show full markdown

Field-tested against tasksquad.ai on 2026-05-03 using a logged-in Chrome session.

URL

code
https://tasksquad.ai/dashboard/agents       # Agents list for current project

Agent list

Agents are the daemon workers that execute tasks. Each agent card shows:

  • Name
  • Status badge (active / inactive / running / waiting_input / paused)
  • Role (optional label set by maintainer)
  • Last-seen timestamp

Navigate to agents via the sidebar link "Agents".

Creating an agent

Maintainer/owner only. Click "New agent" (or similar CTA in the agents view).

Provide:

  • Name — display name for the agent
  • Role (optional) — a freeform string describing the agent's specialty

After creation, a token is generated. Copy it immediately — it is shown only once. The daemon uses this token to authenticate.

code
tsq install --token <TOKEN>

Tokens are created via POST /teams/:teamId/tokens with { label, agent_id }.

Agent statuses

StatusMeaning
activeDaemon connected, ready to accept tasks
inactiveDaemon not connected (no recent ping)
runningCurrently executing a task
waiting_inputPaused mid-task, waiting for user reply
pausedManually paused — will not pick up new tasks

Agent actions (maintainer / owner)

ActionTriggerEffect
Pause/ResumeToggle button on cardSets paused flag — agent ignores new tasks
Reset"Reset" buttonClears the agent's running state (use if stuck)
DeleteDelete button / menuPermanently removes agent and its tokens
Edit roleRole edit controlUpdates the agent's role label

Token management

Tokens are per-agent credentials. Each token has a label. A maintainer can:

  • Generate a new token — use when setting up a new machine or rotating credentials
  • Tokens cannot be viewed after creation; only revoked implicitly by deleting the agent

Gotchas

  • Status is driven by daemon pings, not task state. An agent can be active while no task is running.
  • inactive ≠ paused. Inactive means the daemon process is offline. Paused means a maintainer explicitly suspended it via the UI.
  • Only owners and maintainers can create agents or generate tokens. Members see the list but cannot modify it.
  • Token is shown once. If you miss copying it, you must generate a new one — there is no "reveal token" button.
  • Reset is for recovery only. Use it when an agent is stuck in running after a daemon crash. Do not reset agents mid-task.

Authentication

auth.md

Source
  • Field-tested against tasksquad.ai on 2026-05-03 using a Chrome session.
  • The login page is a centered card with two OAuth buttons. No email/password form exists — SSO only.
  • The card contains exactly two buttons:
  • Both are <button type="button"> inside a <div class="px-6 pb-6 flex flex-col gap-3">. Locate by label text and click coordinates returned from the rendered element:
Show full markdown

Field-tested against tasksquad.ai on 2026-05-03 using a Chrome session.

URLs

code
https://tasksquad.ai/auth          # login page (redirects to /dashboard if already signed in)
https://tasksquad.ai/auth/cli      # CLI token auth page

Login page

The login page is a centered card with two OAuth buttons. No email/password form exists — SSO only.

python
goto_url("https://tasksquad.ai/auth")
wait_for_load()

Sign-in buttons

The card contains exactly two buttons:

Visible labelProvider
"Continue with Google"Google
"Continue with GitHub"GitHub

Both are <button type="button"> inside a <div class="px-6 pb-6 flex flex-col gap-3">. Locate by label text and click coordinates returned from the rendered element:

python
import json

def click_button_by_text(label):
    """Find a <button> by exact innerText and click its center."""
    sel = json.dumps(label)
    result = js(f"""
      var b = Array.from(document.querySelectorAll("button"))
                .find(e => (e.innerText || "").trim() === {sel});
      if (!b) return null;
      var r = b.getBoundingClientRect();
      return JSON.stringify({{x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)}});
    """)
    if result is None:
        raise RuntimeError(f"button not found: {label!r} — has the React app finished hydrating?")
    pos = json.loads(result)
    click_at_xy(pos["x"], pos["y"])

# Google
click_button_by_text("Continue with Google")

# GitHub
click_button_by_text("Continue with GitHub")

After clicking, a browser popup opens for the OAuth flow. Stop and ask the user to complete sign-in — do not attempt to interact with the OAuth popup window.

Auth-wall pattern

Any route under /dashboard/* redirects to /auth when the user is not signed in. If you navigate to a dashboard URL and land on /auth, the session is unauthenticated — ask the user to sign in before proceeding.

Redirect after sign-in

Firebase Auth resolves the session client-side. After the OAuth popup closes, React's onAuthStateChanged fires and automatically navigates the user to /dashboard. Do not click anything — just wait_for_load() and verify with page_info().

Sign-out

There is no dedicated sign-out page. The sign-out action is triggered from the sidebar in /dashboard. Look for a LogOut icon button in the bottom-left sidebar area.

Gotchas

  • The page is a React SPA. Navigating to /auth while the app is still hydrating returns the bare <div id="root"> with no buttons yet. Always call wait_for_load() and verify the "Continue with Google" text is present before clicking.
  • No error routes exist for failed OAuth. On failure, the card renders an inline <p class="text-sm text-red-500 text-center"> error message below the buttons.
  • authed === null loading state. While Firebase resolves the session on /auth, the <Login> component is not rendered (the route renders null). Wait for buttons to appear before clicking.

Task Inbox

tasks.md

Source
  • Field-tested against tasksquad.ai on 2026-05-03 using a logged-in Chrome session.
  • The inbox is the default view after sign-in. It shows a list of tasks assigned to agents in the currently selected project.
  • Tasks are rendered as rows. Each row shows:
  • Subject line
Show full markdown

Field-tested against tasksquad.ai on 2026-05-03 using a logged-in Chrome session.

URL

code
https://tasksquad.ai/dashboard              # Inbox (default view)
https://tasksquad.ai/dashboard/<taskId>     # Task thread (individual task)

Inbox view

The inbox is the default view after sign-in. It shows a list of tasks assigned to agents in the currently selected project.

Task list

Tasks are rendered as rows. Each row shows:

  • Subject line
  • Agent name
  • Status badge
  • Relative timestamp

Status values

StatusMeaning
pendingQueued for the agent daemon
queuedAgent is busy — task is waiting in line
runningAgent is actively working
waiting_inputAgent needs a reply from the user
doneCompleted successfully
failedEnded with an error
scheduledWill start at a future scheduled_at time
wrapping_upRunning post-completion close steps

Filters

Two dropdowns appear above the task list:

Status (left): All / Pending / Queued / Running / Waiting / Done / Failed / Scheduled

Origin (right): All / System / Mine / From Note / Critique / Scheduled

  • "System" = tasks created by automated conveyors
  • "Mine" = tasks you composed yourself
  • "From Note" = tasks spawned from Notes
  • "Critique" = tasks that are note critiques

Both dropdowns use shadcn <Select>. Click the trigger to open, then click the item by text.

Refresh

A RefreshCw icon button sits next to the "Inbox" heading. Click it to reload the task list without full navigation. Alternatively, wait_for_load() after any state change — the app auto-polls when active tasks exist (interval depends on plan; see Gotchas).

Composing a new task

Click the "New message" button (top-right of Inbox). A dialog opens.

Dialog fields

FieldTypeNotes
Agent<Select>Required. Dropdown of agents in the current project.
Subject<input>Required. Short description of the task.
Message<textarea>Optional. Task body / detailed instructions.

Optional advanced toggles (revealed via UI controls):

  • Schedule: set a future delivery time
  • Auto-close: task closes automatically when the agent finishes
  • Save tokens: compress the task context (lite / full / ultra)
  • Close steps: newline-separated post-completion steps

Submit with the "Send" button inside the dialog.

python
import json

def _coords_by_text(label, tag="button"):
    """Find an element by exact innerText and return click coords, or raise."""
    sel = json.dumps(tag)
    txt = json.dumps(label)
    result = js(f"""
      var el = Array.from(document.querySelectorAll({sel}))
                .find(e => (e.innerText || "").trim() === {txt});
      if (!el) return null;
      var r = el.getBoundingClientRect();
      return JSON.stringify({{x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)}});
    """)
    if result is None:
        raise RuntimeError(f"{tag!r} with text {label!r} not found")
    p = json.loads(result)
    return p["x"], p["y"]

def _coords_by_selector(selector):
    """Find an element by CSS selector and return click coords, or raise."""
    sel = json.dumps(selector)
    result = js(f"""
      var el = document.querySelector({sel});
      if (!el) return null;
      var r = el.getBoundingClientRect();
      return JSON.stringify({{x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)}});
    """)
    if result is None:
        raise RuntimeError(f"selector not found: {selector!r}")
    p = json.loads(result)
    return p["x"], p["y"]

# Open the compose dialog
click_at_xy(*_coords_by_text("New message"))
wait(1.0)  # let the dialog mount; agents may still be loading

# Open the agent <Select> trigger and pick an agent.
# The trigger renders the placeholder "Select agent…" until an agent is chosen.
click_at_xy(*_coords_by_text("Select agent…"))
wait(0.5)
# Then click the agent name from the opened dropdown:
click_at_xy(*_coords_by_text("YOUR_AGENT_NAME"))

# Focus the subject input, then type
click_at_xy(*_coords_by_selector('input[id="subject"]'))
type_text("Check the build status")

# (Optional) focus the message textarea and type the body
# click_at_xy(*_coords_by_selector('textarea'))
# type_text("Detailed instructions go here.")

# Submit
click_at_xy(*_coords_by_text("Send"))

Task thread

Clicking a task row opens the thread at /dashboard/<taskId>.

The thread is an email-style conversation. Messages alternate between:

  • User messages (right-aligned or labeled with sender name)
  • Agent messages (left-aligned)

Replying

When a task is in waiting_input status, a reply box appears at the bottom. Type your reply and press Enter or click the send button.

A scheduled reply pending delivery blocks the reply box — a cancel option appears.

Task actions

Actions available from the thread view (usually via icon buttons or a menu):

  • Close — mark the task done manually
  • Delete — permanently remove the task
  • Forward — reassign to a different agent (appears as "Forward to agent" with agent selector and optional instructions)

Gotchas

  • Inbox auto-polls while active tasks exist (pending / running / waiting_input). Free plan polls every 5 s, Pro every 2 s. For scraping, add a wait_for_load() between reads if statuses are changing.
  • queued is a derived client-side status — the server returns pending, but the UI shows queued when the target agent is itself running or waiting_input. Filter accordingly.
  • Task list is per-project. Switching projects (teams) reloads the list. The active project is stored in localStorage as tsq_team_id.
  • Dialog does not open until agents are loaded. If "Select agent…" placeholder is missing after clicking "New message", the agents list is still fetching — retry after a short wait.
  • Free plan project limit: free accounts have a project limit (currently 1).