* feat(onboarding): minimal input: orgnr + moms period is the whole ask
Two fixes from the third E2E attempt (2026-08-26):
1. accounting_method is now optional in CompanySetupSchema and defaults by
form in planCompanySetup: aktiebolag = accrual (the norm), enskild
firma = cash (the common small-EF choice; legal under 3 MSEK, BFL 4
kap 4 paragraf). The plan flags the default (resolved.accountingMethodDefaulted)
and gnubok_create_company's preview carries accounting_method_defaulted
so the readback names it and the user overrides in the same 'ja'.
Never silent: the preview is the checkpoint. Applies to the MCP tool
and POST /api/v1/companies (additive; response shows the resolved
value). The lookup tool's still_to_ask no longer lists it.
2. The agent refused a real orgnr because the user said 'nytt bolag' and
the registry showed an established company ('Stopp. Numret matchar
inte ett nytt bolag'): lookup instructions now state that an
established company with F-skatt/VAT is the NORMAL case (new = new to
Accounted) and the orgnr is never second-guessed for looking
established.
Skill + plugin (v1.2.1) updated; API skill regenerated; DECISIONS.md entry.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(onboarding): surface the kontantmetod 3-MSEK condition on the defaulted cash method
Compliance-review finding on #1952: the EF cash default carries a legal
eligibility condition (turnover normally under 3 MSEK, BFL 4 kap 4 §)
that a client not reading the onboarding skill would never see. The
create preview now carries accounting_method_note with the condition
whenever cash was defaulted, and the v1 pitfall states it for API
integrators. The registry cannot verify turnover, so the confirm-time
human check is the gate; the default itself stays (a brand-new EF has
zero turnover by definition).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
167 lines
8.4 KiB
TypeScript
167 lines
8.4 KiB
TypeScript
import type { Skill } from './types'
|
|
|
|
const body = `# Onboarding: set up a company in Accounted from the conversation
|
|
|
|
From "my company is not in Accounted yet" to a working ledger without the
|
|
user opening the web app first. The only browser steps are the ones that
|
|
legally need a human with BankID: connecting (creating the account),
|
|
approving the bank consent, and authorising Skatteverket. Everything else
|
|
happens here.
|
|
|
|
**Momentum rule: one confirmation, then keep going.** The only stop in this
|
|
flow is the create-company preview ("stämmer detta? ja"). Never end a turn
|
|
with "säg till när du vill fortsätta": after the confirm, call the connect
|
|
tools immediately; when the user reports a connection done, verify it and
|
|
continue straight into import or categorization. Staged writes still go
|
|
through their normal approval, but that approval IS the conversation, not an
|
|
extra pause around it.
|
|
|
|
## When to use
|
|
|
|
- "Sätt upp bokföring för mitt AB / min enskilda firma"
|
|
- "Jag har precis startat bolag, hur kommer jag igång?"
|
|
- "Lägg till ett nytt bolag" (an existing user adding a second company)
|
|
- A byrå/consultant onboarding a new client company (pass \`team_id\`)
|
|
|
|
## Step 0: connect
|
|
|
|
If this session is not connected yet, the first company-scoped call (for
|
|
example \`gnubok_create_company\`) returns an authentication challenge that the
|
|
client shows as a Connect prompt. Tell the user: "Klicka på Connect; har du
|
|
inget konto skapar du det där (BankID eller e-post), det tar en minut." The
|
|
call is retried automatically once connected. Do not send the user to the web
|
|
app to sign up first.
|
|
|
|
## Step 1: THREE opening questions, then look up
|
|
|
|
Open with exactly three questions, together:
|
|
|
|
1. **Organisationsnummer?** (10 digits; an enskild firma's org number is the
|
|
owner's personnummer, fine to use here)
|
|
2. **Har du bokfört i ett annat system tidigare?** (Fortnox, Visma, Bokio,
|
|
Björn Lundén, Briox, Wint, annat system, eller helt nytt bolag)
|
|
3. **Vilken bank har företaget?** (so the bank connect link later opens that
|
|
bank's consent directly instead of a picker)
|
|
|
|
Then call \`gnubok_lookup_company\` with the org number. The registry answers
|
|
most of the form; present the facts as a SHORT summary to confirm ("Jag
|
|
hittade Example AB, Storgatan 1 i Stockholm, godkänd för F-skatt och
|
|
momsregistrerad. Stämmer det?") and ask ONLY what \`still_to_ask\` lists.
|
|
Never re-ask what the registry answered.
|
|
|
|
Rules baked into that split (same as the web onboarding):
|
|
|
|
- **F-skatt** from the registry is a fact, both true and false.
|
|
- **VAT** is a fact ONLY when positively registered. "No VAT registration
|
|
found" is a question, never an assumption (ML 17 kap 24 §).
|
|
- **Moms period** is ALWAYS the user's answer when VAT-registered. Rules of
|
|
thumb if unsure: under 1 MSEK turnover may report VAT yearly, under 40
|
|
MSEK quarterly, above monthly.
|
|
- **Accounting method is NOT a question**: it defaults by form (AB =
|
|
faktureringsmetoden, enskild firma = kontantmetoden) and the preview
|
|
flags the default. Name it in the readback ("faktureringsmetoden,
|
|
standard för AB, säg till om du vill ha kontantmetoden") so the user can
|
|
override in the same "ja". Cash requires turnover under 3 MSEK.
|
|
- **Enskild firma name**: verksamhetsnamnet is freely choosable; suggest the
|
|
registered name but let the user pick. An AB's registered name is a fact.
|
|
- **Fiscal year**: registry data becomes a confirm question, never an open
|
|
one. No closed period in the registry = FIRST räkenskapsår: suggest a
|
|
start at the registration date. The end differs by form: an enskild
|
|
firma MUST end 31 December; an AB may pick any end within 18 months of
|
|
the start (BFL 3 kap 3 §), with 31 December as the common default, so
|
|
present the AB's choice rather than assuming it.
|
|
|
|
\`not_found\`/\`unavailable\`: fall back to asking the \`still_to_ask\` list and
|
|
continue. Only \`aktiebolag\` and \`enskild_firma\` are supported today.
|
|
|
|
## Step 2: preview, ONE confirm, create, keep moving
|
|
|
|
Call \`gnubok_create_company\` WITHOUT \`confirm\`. Read the preview back in
|
|
plain Swedish (form, orgnr, fiscal period dates, VAT + period, method).
|
|
After the user's "ja": call it again with \`confirm: true\`, and in the SAME
|
|
turn continue with step 3 or 4. Creation sets up chart, settings, first
|
|
fiscal period, tax deadlines, and starts the 30-day trial; the connection
|
|
uses the new company automatically.
|
|
|
|
## Step 3 (existing bookkeeping): import it FIRST
|
|
|
|
When the user had a previous system, history comes before the bank: it is
|
|
the fastest path to a ledger that shows real value, and bank history rarely
|
|
reaches far enough back anyway.
|
|
|
|
1. Tell them where to export: **Fortnox** Register → Exportera → SIE 4,
|
|
**Visma eEkonomi** Bokföring → Export SIE, **Bokio** Inställningar →
|
|
Exportera data → SIE, **Björn Lundén / Briox / Wint** under Export.
|
|
Every Swedish system exports SIE4 (.se/.sie); ask them to attach the
|
|
file here in the chat.
|
|
2. When the file arrives, call \`gnubok_sie_preflight\` with its content
|
|
(\`file_content\` as read, or \`file_content_base64\` when exact bytes are
|
|
available: that preserves åäö in CP437 exports). Summarize the scan:
|
|
source system, fiscal years, verifikat count, balance status, org-number
|
|
match, warnings. This is the "does it look correct" moment: surface
|
|
problems BEFORE anything is written.
|
|
3. On their go-ahead: \`gnubok_import_sie\` with the same file and the
|
|
preflight's \`mappings\`. It stages for approval; after commit verify with
|
|
\`gnubok_get_trial_balance\`.
|
|
4. Multiple fiscal years = multiple files: import oldest first so IB/UB
|
|
chains. If the file is very large for chat, the web wizard at
|
|
\`/import?mode=sie\` is the fallback; Fortnox users can also run the full
|
|
API migration (invoices, customers, documents) at
|
|
\`/import?mode=migration&provider=fortnox\`.
|
|
|
|
## Step 4: connect bank and Skatteverket (together, no pause)
|
|
|
|
Call \`gnubok_connect_bank\` (pass \`bank\` from step 1 so the link opens that
|
|
bank's consent directly) AND \`gnubok_connect_skatteverket\` in the same
|
|
turn; on claude.ai/Desktop both render connect cards with buttons.
|
|
|
|
- Bank: BankID + PSD2 consent, then an **account selection dialog** in the
|
|
browser: transactions start syncing when the user saves it. Banks cap
|
|
PSD2 history (often ~90 days); older history is the SIE import's job.
|
|
- Skatteverket: BankID as firmatecknare; enables skattekonto sync and
|
|
moms/AGI filing. Optional, never block on it.
|
|
|
|
When the user says they are done (or comes back), re-call
|
|
\`gnubok_connect_bank\` to verify \`connected\`, then go DIRECTLY to step 5.
|
|
|
|
## Step 5: first bookkeeping, immediately
|
|
|
|
Call \`gnubok_list_uncategorized_transactions\` as soon as the bank is
|
|
connected: do not ask whether to proceed. Walk the categorize flow
|
|
(\`gnubok_suggest_categories\`, \`gnubok_categorize_transaction\`, approval).
|
|
If nothing has synced yet, say so and check again on the user's next
|
|
message instead of making them ask.
|
|
|
|
## Tools
|
|
|
|
- \`gnubok_lookup_company\`: registry facts + prefill from the orgnr; call first
|
|
- \`gnubok_create_company\`: preview (no confirm) then create (confirm=true)
|
|
- \`gnubok_sie_preflight\`: scan a shared SIE file, nothing written
|
|
- \`gnubok_import_sie\`: staged import; use the preflight's mappings
|
|
- \`gnubok_connect_bank\` / \`gnubok_connect_skatteverket\`: status + connect links
|
|
- \`gnubok_list_companies\`, \`gnubok_get_agent_briefing\`: state checks
|
|
- \`gnubok_list_uncategorized_transactions\`: the first real bookkeeping step
|
|
|
|
## Pitfalls
|
|
|
|
- A VAT-registered company without a moms period is refused on purpose; do
|
|
not work around it by claiming the company is not VAT-registered.
|
|
- Do not create a company twice on a retry: check \`gnubok_list_companies\`
|
|
if a create call was interrupted.
|
|
- A preflight org-number mismatch means the file is another company's
|
|
bookkeeping: stop and confirm, never import across companies.
|
|
- Bookkeeping duty starts when the company exists in Accounted with a fiscal
|
|
period. Never create a company "to try things out" for a real
|
|
organisation; use the sandbox in the web app for demos.
|
|
`
|
|
|
|
export const onboardingSkill: Skill = {
|
|
slug: 'onboarding',
|
|
name: 'Onboarding: New Company Setup',
|
|
summary:
|
|
'Set up a company in chat: orgnr + previous system first, prefill via gnubok_lookup_company, one confirm to create, SIE history via preflight + staged import, then bank/Skatteverket cards.',
|
|
tags: ['onboarding', 'setup', 'company', 'bank', 'skatteverket', 'sie', 'migration', 'agent-first'],
|
|
body,
|
|
tier: 'workflow',
|
|
}
|