Appearance
Intent catalogue
Every intent BlazAI understands, what it extracts, and what the UI renders. This is the reference for "can BlazAI do X".
Intent source: bz-agent/src/utils/constant.ts → AVAILABLE_INTENTS
Action source: bz-backend/v1/models/blazMessage.js → BLAZ_ACTIONS
Renderer: defi-dex/src/component/defi/swapAI/BotMessage.tsx
Intent vs action
An intent is what the classifier decided the user wanted. An action is the discriminator that tells the frontend which component to render. They are usually 1:1, but not always — CREATE_DAPP and MODIFY_DAPP both map to the create_dapp action because DappPreview handles both.
Trading & wallet
| Intent | Extracts | Action | Renders |
|---|---|---|---|
SWAP | fromToken, toToken, chain, amount | quotes | quotes/QuotesContainer |
BRIDGE | fromToken, toToken, fromChain, toChain, amount | quotes | quotes/QuotesContainer |
SEND_TOKEN | recipient (address or name.blazpay username), token, amount, chain | send_token | SendTransaction |
BUY | fiat amount, currency, target token | buy_sell | buy/BuyQuoteContainer |
BUY_BZ_TOKEN | amount | buy_bz_token | presale/PresaleMessage |
DCA | frequency (interval multiplier), interval (unit), occurrence (order count), tokens, amount | dca | Dca/Dca |
LIMIT_ORDER | pair, side, target price, amount | limit_order | — no handler; falls through to text |
SWITCH_CHAIN | target chain | switch_chain | Chain-switch card |
CHECK_BALANCE | token and/or chain | check_balance | Balance card |
PORTFOLIO | — | portfolio | portfolio/UserPortfolio |
TX_HISTORY | — | tx_history | actions/TxHistory |
TX_INFO | transaction hash | tx_info | actions/TxInfo |
PRICE_ALERT | token, threshold, direction | price_alert | Alert confirmation |
SWAP versus BRIDGE is decided by whether fromChain and toChain differ. The entry prompt says so explicitly, because users say "swap" for both.
CHECK_BALANCE is also the intent for follow-up questions about worth, price or value of tokens already discussed — that is in its description on purpose, so "how much is that worth?" does not fall through to conversation.
Safety
| Intent | Extracts | Action | Renders |
|---|---|---|---|
CONTRACT_AUDIT | address, chain, source (pasted Solidity), contractName | contract_audit | actions/AuditResult |
TOKEN_SAFETY | token address, chain | token_safety | actions/TokenSafetyResult |
WALLET_CARD | address, ENS, or Blazpay username | wallet_card | actions/WalletCardResult |
REVOKE_APPROVALS | chain (defaults to connected wallet) | revoke_approvals | actions/ApprovalRevoker |
The intent descriptions carry explicit negative examples, because these four overlap heavily in user phrasing:
CONTRACT_AUDITis not for "what is an audit" (that isCONVERSATION) and not for token rug checks (that isTOKEN_SAFETY).TOKEN_SAFETYis token-specific — ownership, mint, blacklist, tax, holder distribution.
See safety suite and contract auditor.
Automation
| Intent | Extracts | Action | Renders |
|---|---|---|---|
AUTOPILOT | sub-action (create/status/pause/resume/close/help) plus a policy draft | autopilot | actions/AutopilotCard |
The description carefully separates Autopilot from its neighbours: it is a persistent budgeted agent with guardrails — not a single one-off swap (SWAP) and not a simple recurring-buy form (DCA). Triggers on "autopilot", "trading agent", "auto-trade my budget", or a budget combined with multiple rules.
Discovery & market data
| Intent | Extracts | Action | Renders |
|---|---|---|---|
NFT_INFO | collection, tokenId, chain, or an OpenSea link | nft_info | actions/NftInfo |
MARKET_INTEL | subject (price / gas / trending / overview / dominance / market cap) | market_intel | Market card |
MARKET_INTEL is for data questions — "price of ETH", "gas on Arbitrum", "top gainers", "BTC dominance" — explicitly not for swapping or trading.
dApp builder
| Intent | Precondition | Action | Renders |
|---|---|---|---|
CREATE_DAPP | — | create_dapp | dapp/DappPreview |
MODIFY_DAPP | An active dApp project in the session | create_dapp | dapp/DappPreview |
SHOW_DAPP | An active dApp project | create_dapp | dapp/DappPreview |
GO_ONCHAIN | An active dApp project | — | Smart-account setup |
DEPLOY_CONTRACTS | An active project and a smart account already set up | — | Deploy flow |
GO_ONCHAIN and DEPLOY_CONTRACTS are easy to confuse
GO_ONCHAIN is first-time smart-account setup ("go onchain", "set up smart account"). DEPLOY_CONTRACTS is deploying Solidity ("deploy my contracts", "deploy via smart account", "generate contracts"). Both descriptions carry explicit do-NOT-use-for lists because the classifier used to conflate them.
The active project is tracked as activeDappProjectId on blazSession and passed to bz-agent with every request, which is how the precondition is enforced.
See dApp builder.
Composition
| Intent | What it does | Action |
|---|---|---|
WORKFLOW | Sequential chained steps — "bridge 1 ETH from Arbitrum to BSC then swap to BNB". Detects "then", "and then", "after that" followed by another action | workflow |
BATCH | Same action, many targets — "send 5 BNB to marcpr, patrickbit, and davidgod". Detects lists, multiple recipients, or the word "each" | batch |
These are genuinely different and the descriptions say so: BATCH is not for sequential chaining, WORKFLOW is not for single intents.
Conversation & fallback
| Intent | When | Action |
|---|---|---|
CONVERSATION | Casual chat, or a question answerable from known context | text → ResponseCard (markdown) |
FALLBACK | No known intent matches, or the model does not know. Routes to vectorNode (RAG lookup over PGVector) then conversationNode | fallback |
FALLBACK's description instructs the model not to generate text — the vector node supplies the grounding instead.
Non-intent actions
Some actions are emitted by the backend without a corresponding classified intent:
| Action | Emitted when | Renders |
|---|---|---|
connect_wallet | An intent needs a wallet and none is connected | ConnectWallet (EVM only) |
error | A handler threw | Text card |
text | Anything conversational | ResponseCard |
history | Legacy | — |
The follow_up convention
Every intent node uses the same pattern:
- If all required fields are present: set
state.intent = AVAILABLE_INTENTS.X.nameandstate.text = 'no-text'. - If something is missing: set
state.intent = 'follow_up'and put the clarifying question instate.text.
So a partially-specified request produces a question rather than a guess. "Swap some ETH" asks how much; it does not pick a number.
Complete action enum
For anyone matching against BLAZ_ACTIONS:
quotes history text error
connect_wallet fallback send_token portfolio
buy_bz_token buy_sell dca tx_info
tx_history nft_info limit_order check_balance
price_alert switch_chain create_dapp contract_audit
token_safety wallet_card revoke_approvals workflow
market_intel batch autopilotMODIFY_DAPP maps to create_dapp, so there are 27 keys and 26 distinct string values.
Adding a new intent
Nine files, three repos, in order. There is a checklist: add an AI intent.
Known gaps
| Intent | Gap |
|---|---|
LIMIT_ORDER | Classifies and extracts, but no backend handler exists. The user gets text, which reads as a failure |
DCA | amount semantic mismatch — template says per-cycle, app deposits as total |
| Perpetuals | No intent at all |
| Liquidity | No intent at all |
| Copy trading | No intent; a read-only COPY_TRADE intent is planned as part of CT-1 |