← Back to Skills

Tawa Intake — ask for what a ticket is waiting on

Half of what sits on a board is one person waiting on one or two facts from one other person. The work is not hard, it is just not *here* — and the loop that…

Commandplatform

About

Half of what sits on a board is one person waiting on one or two facts from one other person. The work is not hard, it is just not *here* — and the loop that closes it is four manual steps: ask, wait, copy what came back onto the ticket, remember to clear the watch.

Skill Content

This is the raw markdown that gets installed as a Claude Code command.

---
description: Ask somebody for the facts a ticket is waiting on, as a portal form, and get the answers back on the ticket by themselves. Use when the thing blocking a ticket is one or two facts in another person's head — bank details, IPs, a hostname, a date, a yes or no — or when asked to "send a form", "ask them for X", or "chase someone for the details". Not for a conversation or a negotiation.
---

# Tawa Intake — ask for what a ticket is waiting on

Half of what sits on a board is one person waiting on one or two facts from one other person. The work is not hard, it is just not *here* — and the loop that closes it is four manual steps: ask, wait, copy what came back onto the ticket, remember to clear the watch.

This command is that loop as one pass. You put the question in front of the person; the portal does the rest.

## What is automatic when a ticket is linked — do not rebuild it

The moment a respondent presses Submit, **the portal already**:

- posts their answers as a comment on the linked ticket, and
- closes that ticket's watch, naming who answered.

That is for a form with a ticket linked. You do not copy answers across, and you do not clear the watch. If a ticket IS linked and you find yourself planning either step by hand, the link did not take — that is the bug, not something to finish manually.

A respondent who edits after submitting produces a second comment saying the answer **changed**. The watch stays closed: nobody is blocked on them again.

## The two things to get right

**Sending is not separable from creating.** `create_form` with `respondents` creates the form *and* emails each person their own link, in one call. There is no way to get a link back and send it yourself — links are credentials and never leave the portal. So **approval happens before the call that carries `respondents`, not after it.**

**Create it empty-handed first.** Pass a `pageKey` and *no* `respondents`, check the form is real, then repeat the same call with `respondents`. The key makes the second call rewrite that same form rather than make a second copy of the questions — so you get a look at it while nobody has been emailed. Without a `pageKey` you have one shot, and a form that turns out not to collect has already reached an inbox.

That is not caution for its own sake. The first attempt at this by hand, in September, collected nothing, and nobody found out until the answers did not arrive.

## Run sequence

### 1. Establish what is actually being asked

Four things. You are usually given two.

| | |
|---|---|
| **Who** | Email addresses. A name is not enough — ask. |
| **Which project** | `find_projects` to resolve it. Never guess a slug. |
| **The questions** | "Get the bank details from Rebecca" is one ask and three questions. Write them out. |
| **The ticket**, if there is one | A ticket that is ALREADY waiting on this answer. `list_portal_tasks`, or `get_task_details` if a key is named. Optional — see below. |

**A ticket is optional, and a form without one is a normal thing to make.** Link a
ticket when one is ALREADY waiting on the answer: that is what makes the answers
post there and the watch close. A survey, a data pull, onboarding details — those
are just forms, and inventing a ticket to hold them only adds a board item nobody
asked for.

A standalone form is not unwatched: it shows who has not answered and for how
long, and it can chase them on its own. Ask for a ticket when somebody is
genuinely blocked, not to satisfy the form.

### 2. Write the questions properly

This is where the command earns its keep — the questions are what the other person actually reads.

- **One fact per question.** "Bank name, account and routing number" is three questions, and three answers you can act on separately.
- **Pick the kind.** `text`, `long`, `choice`, `multi`, `number`, `host`. Use `host` for an IP or hostname — it is validated, so you do not get "the usual one". `choice` when there is a fixed list.
- **`required: false` for anything genuinely optional.** A required question they cannot answer blocks their whole submission, and you get nothing instead of most of it.
- **Write an `intro` saying why.** One sentence. People answer faster when they know what it unblocks.

### 3. Create it, with a key and nobody on it

```
create_form({
  project: "<slug>",
  title: "<what it is>",
  pageKey: "intake-<ticket-key>-<what>",   // stable; makes step 5 a rewrite, not a copy
  ticket: "<KEY>",                          // the loop only closes if this is here
  intro: "<why you are asking>",
  questions: [
    { prompt: "Which bank?", kind: "text" },
    { prompt: "VPN hostname", kind: "host", hint: "or an IP" },
    { prompt: "Anything else we should know?", kind: "long", required: false },
  ],
})
```

Nothing has been sent. The reply says so.

**A warning about the ticket means the answers will land nowhere** — the key resolved to no ticket. Fix it and say what happened; do not send a form whose answers have no home.

### 4. Confirm it is actually collecting

```
find_pages({ project: "<slug>" })
```

Find your form and read three things off it:

| Check | What wrong looks like |
|---|---|
| `type` is `"form"` | Anything else — `artifact`, `page` — **cannot collect answers at all**. Start over as a form. |
| a `form` block is present | No block means the portal is not treating it as a questionnaire. |
| `form.questions` is your count | A short count means a question was dropped in building. |

Open the URL yourself if anything reads oddly. This step costs one call and is the only thing standing between a typo and a form that quietly collects nothing.

`find_pages` is served from a 30-second cache, so a form created a moment ago may read stale. Re-check rather than concluding from the first empty answer.

### 5. Show, then send

Show the questions as they will read, name every recipient, name the ticket. Wait for a yes.

Then repeat **the same call**, with the same `pageKey`, plus the people:

```
create_form({ ...as above, respondents: ["[email protected]"], expiresAt: "<ISO>" })
```

`expiresAt` is optional and stops the links working after that moment — worth setting when the ask has a deadline of its own.

**Read the result rather than assuming it:**

| Result | What to say |
|---|---|
| `shared: true` | They have it. Name who, from `recipients`. |
| `shared: false` + `shareError` | **The form exists and nobody has it.** Say that plainly, give the URL. Not a success. |

A `shareError` about Bio-ID means the session is a `jci_` API key, which cannot send as a person. The form is fine; reconnect with Bio-ID OAuth and repeat the call.

### 6. Open the watch

The portal closes the watch when answers arrive. Something has to open it:

```
update_task({
  taskId: "<KEY>",
  isWatch: true,
  waitingOn: "them",
  sinceDate: "<today>",
  watchEmails: ["[email protected]"],
})
```

`watchEmails` matters: if they reply by email instead of filling the form — which people do — the watch surfaces anyway instead of sitting silent.

### 7. Chasing and harvesting, later

**Who is still owed**, without reading anybody's answers — `find_pages` carries `form.asked`, `answered`, `submitted`, `outstanding`. `outstanding` excludes invitations that were revoked or expired, so it can genuinely reach zero.

**What came back:**

```
read_form_responses({ pageKey: "<the key from step 3>" })
```

(or `{ project, slug }` if the form has no key). The answers are already on the ticket, so this is for reading them in conversation. Report the `report` field — it is the joined, readable version, questions beside answers, with the creator's notes and who has not replied. Do not reassemble it from `respondents` and `questions` by hand.

Report outstanding people as people, not counts — "Rebecca answered, Kyle has not opened it" is the sentence someone can act on.

This needs the caller's own Bio-ID sign-in. On a `jci_` API key session it fails saying so; that is the wrong session, not an access problem to work around.

## What NOT to do

- **Do not send the questions as an ordinary email** because it feels lighter. Then the answers live in a thread and closing the loop is manual again — the thing this exists to stop.
- **Do not build it as an artifact.** An artifact is read-only and cannot collect answers. Four versions of one page looked like they saved and did not; that is why forms exist, and why step 4 checks the type.
- **Do not skip step 4 because the create call said `success`.** It says the page was written, not that it can be answered.
- **Do not copy the answers onto the ticket yourself.** They are already there. A second copy in your words is a second version of the truth.
- **Do not chase in the same breath as asking.** Send it, set the watch, stop. The watch is what remembers.
- **Do not put a secret in a question.** A form asks; it is not a vault. If the fact is a credential, ask for it the way that credential's own system expects.
- **Do not rewrite the questions of a form people have started answering.** The portal refuses, correctly — a repeat with a `pageKey` is a retry, not a way to change the question under a respondent.

## When this is the wrong tool

If the ask is a conversation — a negotiation, a decision needing discussion, anything whose reply is a paragraph with its own questions — draft a reply instead. A form is for facts with a shape. Using one for a discussion reads as a customer-service portal and gets ignored.

## Where this lives

The portal side is INSURECO-50: the `form` page type, per-respondent answers, role-based reads, one-time share links, and the ticket link that closes the loop. The tools (`create_form`, `read_form_responses`) are jci-mcp; the same content ships as the `intake` skill on claude.ai from `jci-mcp/skills/intake/`. Change both together, or they drift.

Install

Copy the skill content and save it to:

~/.claude/commands/tawa-intake.md
Download .md

Coming soon via CLI:

tawa chaac install tawa-intake

Details

Format
Command
Category
platform
Version
1.0.87433
Tokens
~2,465
Updated
2026-10-13
platform