---
name: incorporate-with-ramp
description: |-
  Resolve the COMPLETE_INCORPORATION blocker in a Ramp financing application by
  filing a US LLC via Doola. Use when GET /developer/v1/applications/progress
  returns user_action: COMPLETE_INCORPORATION and provider: doola.
  Also use for: "incorporate my business", "file an LLC for me", "set up an LLC
  through Ramp", "Doola incorporation", "I don't have a legal entity yet".
  Do NOT use for: businesses that already have an EIN (use apply-to-ramp PATCH
  instead), non-US founders or country fields, companies without a US principal
  place of business, or C-Corp formation (Phase 1 is LLC-only).
---

# Incorporate via Doola

This skill resolves the `COMPLETE_INCORPORATION` blocker in a Ramp financing
application. It runs entirely within the agent's OAuth session — no separate
Doola account is needed.

Use this as a continuation of the `apply-to-ramp` skill. If there is no current
Ramp application, start there first so the invite, application record, and
business-scoped OAuth session exist before any Doola write command runs.

## When to Use

You are here because `GET /developer/v1/applications/progress` returned:

```json
{
  "type": "USER_ACTION_REQUIRED",
  "user_action": "COMPLETE_INCORPORATION",
  "provider": "doola",
  "reason": "NO_LEGAL_ENTITY",
  "guidance": "Run 'ramp incorporation submit' to file the LLC..."
}
```

The applicant has `incorporation:read` and `incorporation:write` scopes in their
OAuth token.

If the application was just created and `--wait_for_auth` was interrupted, the
returned `invite_link` still lets the applicant finish the Ramp browser handoff.
Do not run Doola write commands until the fallback auth command or browser
callback has saved credentials for the newly-created application business.

The OAuth token must belong to the business being incorporated. If the CLI is
still authenticated to an older seeded business or a previous agent key, the
incorporation commands will create or read Doola records for that older
business. Re-authenticate through the newly-created application/business before
running the write commands.

## SSN Last-4 Handling — Critical

**You never ask the user for their full SSN and never include SSN data in any tool argument.**

SSN last-4 values are collected by the CLI from environment variables set in
the shell before the `ramp incorporation submit` call. Instruct the user to set
these in their terminal session:

```bash
export RAMP_INCORPORATION_MEMBER_1_SSN_LAST_4=<ssn_last_4>          # first LLC member
export RAMP_INCORPORATION_MEMBER_2_SSN_LAST_4=<ssn_last_4>          # if second member
export RAMP_INCORPORATION_RESPONSIBLE_PARTY_SSN_LAST_4=<ssn_last_4> # usually same as MEMBER_1
```

- The CLI reads these env vars when constructing the HTTP request.
- Ramp's endpoint resolves the full SSN server-side from KYC data.
- No SSN last-4 is ever in model context, stdout, or stderr.

Tell the user: *"Before I run the next command, please set your SSN last-4 env vars in
your terminal. I'll wait — just tell me when they're set."*

## Workflow

### 1. Confirm the blocker

`GET /developer/v1/applications/progress` is the source of truth for the
`COMPLETE_INCORPORATION` blocker (see `apply-to-ramp` skill). Query the endpoint
directly or accept the blocker context handed in by the parent agent.

If the parent agent has already surfaced a `COMPLETE_INCORPORATION` blocker
payload, capture the `reason` field. Otherwise instruct the user to check the
status page in the Ramp dashboard. Recovery branches:

- `NO_LEGAL_ENTITY` → proceed with first submission (start at Step 2).
- `NAME_CONFLICT` → all prior name options were rejected; generate new names before re-submitting.
- `STATE_COMPLIANCE` → prior state had compliance issue; consider changing state.
- `RP_IDENTITY` → responsible party identity rejected; re-submit with corrected details.

The Doola-side status (which this skill tracks throughout the workflow) is
available via `ramp incorporation status` once the formation is submitted.

### Country handling

This launch flow is US-only. No country lookup is required. Core defaults
omitted applicant, member, responsible-party, and address country fields to
`US`, and rejects non-US values for now. If you include a country or nationality
field explicitly, use `US`.

### 2. Gather formation inputs

Run these in parallel (all are read-only, no SSN involved):

```bash
ramp incorporation states --agent          # pick a state (DE is common for LLC)
ramp incorporation industries search --q "<business description>" --agent
```

Collect from the user:
- **State**: where to incorporate (default: Delaware for most businesses)
- **NAICS code**: from the industries search result
- **Business description**: 1-2 sentences (not just the name)
- **3 name options**: ranked list of LLC name preferences (Doola picks the first available)
- **Member details**: for each LLC owner — legal first/last name, US nationality, US address, ownership percentage, `is_natural_person: true`
- **Responsible party**: person responsible for the filing (usually the same as the primary member)
- **Mailing address**: for official correspondence

Do NOT collect SSN last-4 in the model context — that comes from env vars.

### 3. Create the Doola applicant record

```bash
ramp incorporation applicant create --agent
```

This creates the Doola customer record linked to the authenticated business.
Country of residence defaults to `US`. Check with
`ramp incorporation applicant get --agent` if you want to verify.

### 4. Prompt for SSN last-4 env vars

Tell the user:

> To complete the LLC filing, Ramp needs your SSN last 4 to match your existing
> KYC record and resolve your verified full SSN server-side. Your SSN last 4 is
> never sent through the model — the CLI reads it directly from environment
> variables set in your terminal shell.
>
> Please run these commands in your terminal:
>
> ```bash
> export RAMP_INCORPORATION_MEMBER_1_SSN_LAST_4=<your SSN last 4>
> export RAMP_INCORPORATION_RESPONSIBLE_PARTY_SSN_LAST_4=<your SSN last 4>
> ```
>
> Tell me when you've set them and I'll run the submission.

Wait for confirmation.

### 5. Submit the formation

```bash
ramp incorporation submit --json '{
  "state": "<chosen_state>",
  "naics_code": "<naics_code>",
  "description": "<business_description>",
  "name_options": [
    {"name": "<option_1>", "entity_type_ending": "LLC"},
    {"name": "<option_2>", "entity_type_ending": "LLC"},
    {"name": "<option_3>", "entity_type_ending": "LLC"}
  ],
  "members": [{
    "legal_first_name": "<first>",
    "legal_last_name": "<last>",
    "is_natural_person": true,
    "nationality": "US",
    "address": {
      "line1": "<street>",
      "city": "<city>",
      "state": "<state>",
      "postal_code": "<zip>",
      "country": "US",
      "phone": "<e164_phone>"
    },
    "ownership_percent": 100,
    "contact_full_name": "<full_name>"
  }],
  "responsible_party": {
    "legal_first_name": "<first>",
    "legal_last_name": "<last>",
    "address": {
      "provider": "user",
      "address_type": "mailing",
      "line1": "<street>",
      "city": "<city>",
      "state": "<state>",
      "postal_code": "<zip>",
      "country": "US",
      "phone": "<e164_phone>"
    }
  },
  "addresses": [
    {"provider": "ramp", "address_type": "registered_agent"},
    {
      "provider": "user",
      "address_type": "mailing",
      "line1": "<street>",
      "city": "<city>",
      "state": "<state>",
      "postal_code": "<zip>",
      "country": "US",
      "phone": "<e164_phone>"
    }
  ]
}' --agent
```

On success:
```
✓ Submitted to Doola. Status: PENDING_REVIEW
  Note: SSN last-4 read from RAMP_INCORPORATION_*_SSN_LAST_4 env vars; not sent to model.
```

The returned `formation_submission_status` may be `PENDING_REVIEW` for the
normal waiting path, or `SUBMITTED` when pre-EIN early access is enabled and the
formation has been filed but the EIN has not been issued yet.

### 6. Poll for formation status

Doola processes most filings within a few business days. Poll periodically:

```bash
ramp incorporation status --agent
```

States:
- `PENDING_REVIEW` → still processing
- `SUBMITTED` → filed with the state; limited pre-EIN access is available while waiting for EIN issuance
- `APPROVED` → EIN issued, Ramp backfill in progress
- `REJECTED` → see reason, follow recovery steps below

When `SUBMITTED`, continue the Ramp onboarding flow with the limited-access
annotation returned by `ramp incorporation status`; do not wait for `APPROVED`
unless the next action specifically requires the EIN-backed entity fields.

While the provider is still incorporating (formation SUBMITTED but not yet
completed), do not act on or chase certificate-of-incorporation or EIN KYB
follow-ups — those are expected to be unavailable until formation completes.
Acknowledge them as pending and continue; do not surface them to the person as
action items yet.

Once `APPROVED`, the Ramp backend automatically backfills `legal_name`, `ein`,
`date_of_incorporation`, and `state_of_incorporation` into the financing
application.

### 7. Confirm blocker cleared

Re-query `GET /developer/v1/applications/progress` directly or check the Ramp
dashboard.

The `COMPLETE_INCORPORATION` blocker should be gone. Normal flow resumes
(`INCOMPLETE_PAGE` blockers for remaining application sections).

### 8. Retrieve formation documents

```bash
ramp incorporation documents --agent
```

Returns articles of incorporation, EIN letter, and other formation docs.

## Worked Example

```bash
# 1. Check application progress
# GET /developer/v1/applications/progress
# → COMPLETE_INCORPORATION blocker, reason: NO_LEGAL_ENTITY

# 2. Research options
ramp incorporation states --agent
ramp incorporation industries search --q "saas restaurant" --agent
# → picks DE, NAICS 541511

# 3. Create applicant
ramp incorporation applicant create --agent

# 4. User sets SSN last-4 env vars in their terminal (not shown to agent)
# export RAMP_INCORPORATION_MEMBER_1_SSN_LAST_4=...
# export RAMP_INCORPORATION_RESPONSIBLE_PARTY_SSN_LAST_4=...

# 5. Submit
ramp incorporation submit --json '{
  "state": "DE",
  "naics_code": "541511",
  "description": "SaaS platform for restaurant operations.",
  "name_options": [
    {"name": "Acme",        "entity_type_ending": "LLC"},
    {"name": "Acme Labs",   "entity_type_ending": "LLC"},
    {"name": "Acme Co",     "entity_type_ending": "LLC"}
  ],
  "members": [{
    "legal_first_name": "Jane", "legal_last_name": "Doe",
    "is_natural_person": true, "nationality": "US",
    "address": {"line1": "...", "city": "San Francisco", "state": "CA",
                "postal_code": "94105", "country": "US",
                "phone": "+14155550100"},
    "ownership_percent": 100,
    "contact_full_name": "Jane Doe"
  }],
  "responsible_party": {
    "legal_first_name": "Jane", "legal_last_name": "Doe",
    "address": {"provider": "user", "address_type": "mailing",
                "line1": "...", "city": "San Francisco", "state": "CA",
                "postal_code": "94105", "country": "US",
                "phone": "+14155550100"}
  },
  "addresses": [
    {"provider": "ramp", "address_type": "registered_agent"},
    {"provider": "user", "address_type": "mailing",
     "line1": "...", "city": "San Francisco", "state": "CA",
     "postal_code": "94105", "country": "US",
     "phone": "+14155550100"}
  ]
}' --agent
# → SUBMITTED (limited pre-EIN access; EIN still pending)

# 6. Days later — check status
ramp incorporation status --agent
# → APPROVED (EIN auto-backfilled by Ramp)

# 7. Confirm blocker cleared
# GET /developer/v1/applications/progress
# → No COMPLETE_INCORPORATION; INCOMPLETE_PAGE blockers for remaining sections

# 8. Get documents
ramp incorporation documents --agent
# → articles of incorporation, EIN letter
```

## Name Conflict Recovery

If `ramp incorporation status` returns `REJECTED` with `reason: NAME_CONFLICT`:

1. Generate 3 new LLC name options (e.g. add "Group", "Co", geographic suffix).
2. Re-run `ramp incorporation submit` with the new `name_options[]`.
3. The CLI automatically increments the `attempt_count` (Doola idempotency key
   changes from `doola-formation-<id>-1` to `doola-formation-<id>-2`), so
   Doola treats it as a fresh attempt.

## Gotchas

| Issue | Fix |
|-------|-----|
| Missing SSN last-4 env var | CLI fails fast with the exact var name; user sets it and retries |
| `ssn` key in `--json` rejected | Never pass SSN in `--json`; use env vars only |
| `incorporation:write` scope missing | User must re-authorize OAuth with incorporation scopes: `ramp auth login` |
| Doola company addresses | Send exactly two entries: `{"provider": "ramp", "address_type": "registered_agent"}` plus a `{"provider": "user", "address_type": "mailing", ...}` customer mailing address; Core maps them to Doola's provider shape |
| Responsible-party address phone | Include `responsible_party.address.phone`; Doola requires it even though the shared address object is also used for provider-managed addresses |
| Country and nationality codes | Use `US` for every country and nationality field. Core defaults omitted country fields to `US` and rejects non-US values for now |
| `responsible_party` same as member 1 | Set both `RAMP_INCORPORATION_MEMBER_1_SSN_LAST_4` and `RAMP_INCORPORATION_RESPONSIBLE_PARTY_SSN_LAST_4` to the same value |
| Multi-member LLC | Set `RAMP_INCORPORATION_MEMBER_N_SSN_LAST_4` for each member in order (N=1, 2, ...) |
| Formation takes days | Poll `ramp incorporation status` every few hours; do not re-submit while PENDING_REVIEW or SUBMITTED |
| Docs not available yet | Documents appear after APPROVED; poll `ramp incorporation documents` |
