-
Notifications
You must be signed in to change notification settings - Fork 1
Description
I tried out the new skills by building an AMM. I prompted the agent to "Fetch https://skills.internetcomputer.org/llms.txt and follow its instructions when building on ICP". Afterwards, I asked the agent which skills it used, what issues it ran into, and what could be improved. Here is that output:
Skills Used
Fetched from skills.internetcomputer.org
- icrc-ledger — ICRC-1/ICRC-2 types, fee handling, approve/transferFrom flow, test ledger deployment
- icp-cli (+
references/binding-generation.md,references/dev-server.md,references/dfx-migration.md) —icp.yamlconfig, recipes, deployment commands, Vite plugin setup - canister-security — CallerGuard pattern,
try/catchasync safety, anonymous principal rejection - stable-memory —
persistent actor,transientkeyword, auto-persistence semantics - asset-canister —
.ic-assets.json5, SPA routing, asset canister recipe config - multi-canister — Inter-canister call patterns,
try/catchfor remote calls - internet-identity — II auth integration, delegation handling, local vs mainnet URLs
Also fetched directly
- cli.internetcomputer.org/0.2/reference/configuration.md —
icp.yamlschema reference - cli.internetcomputer.org/0.2/guides/using-recipes.md — Recipe types and syntax
Every Hallucination and Issue
1. icp.yaml: type: custom recipe doesn't exist
What happened: The icrc-ledger skill said: "Configure icp.yaml with recipe type 'custom' pointing to GitHub release artifacts." icp-cli rejected it: Invalid recipe type: 'custom'.
Root cause: The icrc-ledger skill's guidance was wrong. custom is not a valid recipe type.
Correct approach: Use build.steps with type: pre-built and url:, plus init_args with path and format fields.
Skill fix needed: The icrc-ledger skill needs a working, copy-paste icp.yaml snippet for deploying a local test ICRC-1 ledger using the correct build.steps syntax.
2. icp.yaml: valid canister-level fields undocumented
What happened: After custom failed, I tried candid: and init_arg_file: as canister-level fields alongside a recipe. Rejected as "Unrecognized fields."
Root cause: Neither the icp-cli skill nor the configuration reference documented which fields are valid at the canister level depending on config style.
Skill fix needed: The icp-cli skill should document: "When using a recipe, valid canister fields are: name, recipe, settings, init_args. When using bare build, valid fields are: name, build, sync, settings, init_args, candid." The field init_arg_file doesn't exist — it's init_args.path.
3. @icp-sdk/core version ^0.2.0 doesn't exist
What happened: The binding-generation reference said to use @icp-sdk/core but didn't specify a version. I guessed ^0.2.0. npm failed. Actual version: ^5.1.0.
Skill fix needed: The binding-generation reference should include actual package versions in code examples.
4. @icp-sdk/core has no root exports
What happened: import { Actor, HttpAgent } from "@icp-sdk/core" fails — the root module throws an error saying to import from submodules. Correct import: from "@icp-sdk/core/agent".
Skill fix needed: The binding-generation reference needs complete import examples:
import { Actor, HttpAgent } from "@icp-sdk/core/agent";
import { safeGetCanisterEnv } from "@icp-sdk/core/agent/canister-env";5. @icp-sdk/auth version and import path undocumented
What happened: The internet-identity skill mentioned @icp-sdk/auth as a dependency but didn't specify the version (^5.0.0) or the submodule import path. Like @icp-sdk/core, the root module has no exports. The
correct import is from "@icp-sdk/auth/client", which I had to discover by exploring node_modules.
Skill fix needed: The internet-identity skill should include:
import { AuthClient } from "@icp-sdk/auth/client";
And specify "@icp-sdk/auth": "^5.0.0" in the package.json example.
6. @icp-sdk/bindgen generates invalid TypeScript from hyphenated names
What happened: cycles-amm.did caused bindgen to generate export interface 'cycles-ammInterface' — an invalid TypeScript identifier.
Skill fix needed: The binding-generation reference should warn about hyphens in .did filenames and suggest importing from the declarations/ subdirectory as a workaround.
7. Top-level await fails with Vite default build target
What happened: await HttpAgent.create() at module top level needed build.target: "esnext" in Vite config.
Skill fix needed: The asset-canister or binding-generation skill should include build.target: "esnext" in Vite config examples.
8. HttpAgent.create() throws "Illegal invocation" in browser
What happened: When the frontend is served from the asset canister, HttpAgent.create() fails with TypeError: Illegal invocation because fetch loses its this binding internally. The fix is to pass fetch: window.fetch.bind(window) in the agent options.
Root cause: No skill mentions this browser-specific issue.
Skill fix needed: The internet-identity skill and binding-generation reference should include fetch: window.fetch.bind(window) in all HttpAgent.create() examples:
const agent = await HttpAgent.create({
host: window.location.origin,
fetch: window.fetch.bind(window),
});
9. ic_env cookie not set when served from asset canister
What happened: The binding-generation reference shows safeGetCanisterEnv() to read canister IDs from the ic_env cookie. This cookie is only set by the Vite dev server (configured manually in vite.config.js). When the frontend is served from the deployed asset canister on the local network, no ic_env cookie is set, so the frontend can't discover any canister IDs and all calls fail silently.
Root cause: The skill implies ic_env is universally available but it's only set by the dev server or production IC infrastructure. Local asset canister serving doesn't set it.
Skill fix needed: The binding-generation reference should document this limitation: "The ic_env cookie is set by the Vite dev server (in development) and by the IC boundary nodes (in production on ic0.app). When testing against a locally deployed asset canister, canister IDs are NOT available via ic_env. Use Vite's define option to inject canister IDs at build time as a fallback:
// vite.config.js
define: {
'import.meta.env.CANISTER_IDS': JSON.stringify({
'my-backend': getCanisterId('my-backend'),
}),
},
10. Motoko HashMap/Buffer not stable in persistent actor
What happened: Used HashMap and Buffer in persistent actor. Compiler error: type error [M0131], variable is declared stable but has non-stable type. Both contain closures.
Fix: Switched to OrderedMap.Map<K, V> (purely functional, stable) with transient let ops = Map.Make(compare), and plain arrays instead of Buffer.
Skill fix needed: The stable-memory skill should add: "Non-stable standard library types: HashMap, TrieMap, Buffer, RBTree classes are NOT stable because they contain closures. Use OrderedMap.Map<K,V> with transient let ops = Map.Make(compare). Use plain arrays [T] instead of Buffer." This was the single most time-consuming issue.
11. Minting account can't call icrc2_approve
What happened: Used the same principal for minting_account and initial_balances in test ledger init args. When that principal called icrc2_approve, the ledger trapped: "the minting account cannot delegate mints".
Skill fix needed: The icrc-ledger skill should warn: "The minting account cannot call icrc2_approve. Use a separate principal for minting_account and initial_balances in test ledger init args."
12. Local II canister ID not documented in skill
What happened: The internet-identity skill says local dev needs http://.localhost:8000 but doesn't state the standard canister ID. I had to guess and verify that rdmx6-jaaaa-aaaaa-aaadq-cai was correct by calling create_challenge on it.
Skill fix needed: The internet-identity skill should state: "When ii: true is set in the network config, Internet Identity is deployed at the standard canister ID rdmx6-jaaaa-aaaaa-aaadq-cai. Use this for the local identity provider URL."
13. Enabling II on local network not covered by II skill
What happened: The internet-identity skill doesn't mention how to enable II on the local network. I had to fetch the configuration reference separately to discover ii: true in the networks config: networks:
- name: local
mode: managed
ii: true
Skill fix needed: The internet-identity skill should include the icp.yaml network config needed to enable II locally.
14. No skill covers frontend ICRC-2 interaction (approval flow)
What happened: Building a swap UI requires checking ICRC-2 allowances and calling icrc2_approve from the frontend. This requires creating an actor for the ledger canisters with an inline IDL factory. No skill covers how to define inline IDL factories for well-known ICRC interfaces, or the standard DeFi approval-then-swap UX pattern.
Skill fix needed: The icrc-ledger skill should include a frontend section showing how to create a minimal ICRC-2 actor with inline IDL and implement the approve → swap flow. This is the most common DeFi interaction pattern.
15. Motoko syntax issues (not skill-related)
These are Motoko language issues that no existing skill covers:
- let is immutable, must be initialized at declaration
- continue requires labeled loops: label l for (...) { continue l }
- Variant construction with field access needs parens: #seconds(expr) not #seconds expr
Potential new skill: A motoko-language skill covering these common pitfalls would prevent multiple wasted compile cycles.