Skip to main content
The server exposes 13 tools. Seven run the formation flow, one operation each: start_formation, create_checkout_session, verify_payment, search_industries, save_company_details, request_ssn_entry_link and submit_formation. Five more handle status, multi-company management and inspection, and report_missing_capability takes reports of anything the others can’t do.
Conventions. Identity comes from the OAuth bearer, so no tool takes a customerId argument. Tool descriptions are agent-facing and double as the agent’s playbook. The flow is server-driven: every formation response carries nextAction (follow it verbatim) and nextActionInput, so the host doesn’t plan the multi-step flow itself. nextActionInput is a {tool, arguments} template, not a payload to echo: call that tool and replace every <placeholder> in arguments with the user’s real answer. A call that still carries a placeholder is rejected with INVALID_INPUT and saves nothing.Intent. Every tool also accepts a top-level context string: one sentence on why the agent is making the call. It is optional on every tool except report_missing_capability, where it is the report itself and required. Elsewhere it feeds doola’s usage analytics only, no tool acts on it, and leaving it out changes nothing. Keep it general and free of personal details.Conversation. Every response carries a conversation_id, and every tool accepts it back as an optional top-level string. Leave it out on the first call, then pass the value from the previous response unchanged on every later call in the same conversation. It only groups one conversation’s calls in doola’s usage analytics: no tool acts on it and it grants nothing. A value that isn’t a well-formed UUIDv7 is replaced with a new one.

Formation tools

The server gates payment and everything after it. create_checkout_session refuses to run until start_formation has saved the legal name, country of residence and company name, and each save_company_details section waits for payment and its own prerequisites. A gated call returns PRECONDITIONS_NOT_MET with the missing steps and the nextAction that gets you unstuck. start_formation, verify_payment and the read-only search_industries are not gated.

start_formation

Starts the formation of an LLC or a C-Corp. Every argument is optional and is saved as given, so call it as soon as the user answers. state and entityType default to a Wyoming LLC, so {} sets that when the user has no preference. The user chooses the entity type; the agent explains the options and never picks for them.

create_checkout_session

Accepts doola’s Terms of Service for the Starter package on the user’s behalf and creates the Stripe checkout. Show the user the Terms link and call it only after they agree. A call without termsAccepted: true is refused with INVALID_INPUT before anything is accepted or created. Returns:
  • pricing: the first-year list price. Quote pricing.summary verbatim and never call it “charged today”, since discounts apply at checkout.
  • chargeSummary: what Stripe charges today, after any discount. Quote it verbatim.
  • checkoutUrl: paste it verbatim into the reply, never a placeholder.
  • checkoutSessionId: keep it for verify_payment.
  • companyId and companyName: the company this checkout pays for. Name it to the user.

verify_payment

Checks with Stripe whether the checkout was paid. Call it once the user says they’ve paid. Returns paymentStatus (Complete when done), the amount paid, and companyId / companyName for the company the checkout was opened for. A Complete payment makes that company the active one, so save_company_details and submit_formation write to it. Ask no post-payment question until it returns Complete.

search_industries

Read-only. Takes no arguments and returns the industries a company can be filed under. Match the user’s description of the business against the list, offer the closest entries, and pass the one they pick, verbatim, as industry to save_company_details.

save_company_details

Saves the post-payment details. Every argument is optional and is saved as given, so save each answer as soon as the user gives it. Sections are written in the order below and the call stops at the first one that fails; the response’s saved array lists what was written before that.

request_ssn_entry_link

doola turns this tool on per environment. While it is off, the server does not list it, get_company_onboarding_status never suggests it, and doola collects the SSN by email with the SS-4.
For a responsible party who lives in the US, the EIN application needs their Social Security Number. No tool accepts one, so this hands the customer a single-use link to a doola-hosted page instead, the way create_checkout_session hands out Stripe’s checkout. The customer signs in to doola with the account the agent is connected to (the page refuses any other account, so a forwarded link cannot be used to phish someone else’s SSN) and types the SSN there and it goes straight to doola, never through the client’s transcript, a tool result or doola’s analytics. Takes no arguments, and is refused with PRECONDITIONS_NOT_MET until the responsible party is saved.
  • A client that declared URL-mode elicitation gets an input_required result asking it to open the page. Its retry checks with doola whether the SSN arrived. If it has, the flow moves on. If not, the customer is usually still on the page, so no second link is sent and nextAction says to confirm with get_company_onboarding_status once they are done.
  • Any other client gets ssnEntryUrl (paste it verbatim) and expiresInMinutes, with the same link in nextAction. The link works once and expires after 15 minutes; call the tool again for a fresh one, which retires any earlier link for the company.
  • Every result carries responsiblePartySsnOnFile, a boolean. No tool ever returns the SSN or any part of it.
It is never a gate: a customer who would rather not can still file, and doola collects the SSN by email with the SS-4. A responsible party living outside the US gets no link and the emailed SS-4 as before.
Never ask for an SSN or ITIN in the chat, and never repeat or save one the customer types anyway.

submit_formation

Files the company with its formation state’s Secretary of State and emails IRS Form SS-4 and Form 8821 to the responsible party for signing. Refused with PRECONDITIONS_NOT_MET, listing missing, while any earlier step is incomplete. A successful filing returns companyId and companyName, the company that was filed.
submit_formation is irreversible. Always present a complete summary table and require an explicit “submit” before calling it. Editing after submission may incur extra costs or delays.

Response fields

Every formation tool’s response shares these steering fields: Error code values: INVALID_INPUT, PRECONDITIONS_NOT_MET, READINESS_CHECK_FAILED, FILING_FAILED. See Errors.

Helper tools

The canonical “where am I?” entry point. Call it once per session, right after the OAuth handshake. No arguments. Returns the customer profile, inferred completed steps, responsiblePartySsnOnFile (a boolean, never the SSN), and a suggestedNextStep + nextActionInput that name the next formation tool to call.Don’t call it before every step, since each formation response already carries nextAction + nextActionInput. Re-call it only when the user returns mid-flow and asks “where are we?”, after an unexpected error, or after switch_active_company. If the customer has no active company yet, it steers you to start_formation.
Returns every company the authenticated customer owns. Use when the user asks “which companies do I have?”, wants to switch context, or before starting a new formation.Returns: companies[] (companyId, name, state, entityType, dashboardStatus, submitted, isActive) and activeCompanyId. The entry with isActive: true is the one the formation tools currently operate on.
Begin a brand-new company formation alongside existing companies. Call it when the customer explicitly asks to form a second (or further) company. Creates an empty in-progress company, links it to the customer, and pins it as active. The previously active company is untouched and stays in list_companies.Returns: companyId (the new active company), suggestedNextStep (start_formation), and the nextAction and nextActionInput template for that first call.
Point the formation tools at a different company the customer already owns. Returns the same shape as get_company_onboarding_status for the newly active company.Parameter: companyId (string, required). Must be one of the IDs returned by list_companies; unknown IDs are rejected.
Returns the active company’s full profile: name, state, entity type, EIN, industry, dashboard status, formation filing date, members, responsible party, addresses, name options, and provisioned services. People carry an ssnOnFile boolean in place of any SSN. Use it for “tell me about my company”, “what’s my EIN?” or “who are the members?”. It differs from get_company_onboarding_status, which returns derived next-step routing rather than raw data.Parameters: none. To inspect a different company, call switch_active_company first.
Call when the user wants something none of the other tools can do. The report is recorded for doola’s team; it reads no customer data, changes nothing on the account, and returns no new tools. Tell the user the capability isn’t available here and point them to the doola dashboard.Parameter: context (string, required). The goal and the kind of tool that would help, in general terms with no personal details.
Last modified on October 29, 2026