Found during QA of #103 (Hermes step A.5).
Repro
Call buy_skill after a successful verify_skill in the same session, omitting creatorWallet — which the tool's own description explicitly invites: "The wallet address of the skill creator (to receive payment). If unknown, leave undefined."
{"name":"buy_skill","arguments":{"skillId":"Gbzs1pwQXrayFoFizpWSfFqvgCuzNWHUC4Noc57FXazy"}}
Result — every time, on every skill tried (reproduced on 2 different skills from 2 different creators):
Failed to buy skill: Simulation failed.
Message: Transaction simulation failed: Error processing Instruction 1: custom program error: 0x7d1.
Logs:
...
Program log: AnchorError caused by account: config. Error Code: ConstraintHasOne. Error Number: 2001.
Program log: Left:
Program log: 8QWrZjNNFzngKWCLCrFkAy7ydnagrBSVYdJFyEvw9agh <- the skill's real creator
Program log: Right:
Program log: 7zRzFeGuCY8aS5Z7DCF2ZBMxUXw1LKZo6m4DC8oQ9mDK <- the BUYER's own wallet
...
Passing the correct creatorWallet explicitly makes the buy succeed (tx confirmed on devnet, balance drops, SKILL.md installs). So the on-chain program and guard logic are both fine — the bug is entirely in how the client resolves the default.
Root cause
packages/core/src/skill-market/index.ts:325:
const creatorWallet = (args?.creatorWallet as string) || defaultCreatorWallet;
defaultCreatorWallet is wired from mcp-stdio.ts:70 as the connected wallet's own address (createAgentMcpServer(conn, wallet, address, ...)), not a lookup of the skill's actual on-chain creator. So omitting creatorWallet silently substitutes the buyer's own address into the creator slot of buyItemIx, which the on-chain program's has_one constraint on config.creator then rejects.
Impact
Any caller that follows the tool's own instructions (omit creatorWallet when unknown) cannot buy anything. In practice this is most callers — creatorWallet is only known if the LLM happens to carry it over from an earlier search_skills result in the same context. This blocks the entire buy flow for any host/agent that doesn't thread that field through by hand.
Suggested fix
Either:
- Look up the skill's real creator on-chain (the
config PDA already stores it) when creatorWallet is omitted, instead of defaulting to the buyer's own address, or
- Drop the parameter entirely and always resolve the creator server-side —
search_skills/verify_skill already return the creator address, so the client never needs to supply it.
Also worth updating the buy_skill tool description, since it currently tells the agent to do the one thing that guarantees failure.
Found during QA of #103 (Hermes step A.5).
Repro
Call
buy_skillafter a successfulverify_skillin the same session, omittingcreatorWallet— which the tool's own description explicitly invites: "The wallet address of the skill creator (to receive payment). If unknown, leave undefined."{"name":"buy_skill","arguments":{"skillId":"Gbzs1pwQXrayFoFizpWSfFqvgCuzNWHUC4Noc57FXazy"}}Result — every time, on every skill tried (reproduced on 2 different skills from 2 different creators):
Passing the correct
creatorWalletexplicitly makes the buy succeed (tx confirmed on devnet, balance drops, SKILL.md installs). So the on-chain program and guard logic are both fine — the bug is entirely in how the client resolves the default.Root cause
packages/core/src/skill-market/index.ts:325:defaultCreatorWalletis wired frommcp-stdio.ts:70as the connected wallet's own address (createAgentMcpServer(conn, wallet, address, ...)), not a lookup of the skill's actual on-chain creator. So omittingcreatorWalletsilently substitutes the buyer's own address into the creator slot ofbuyItemIx, which the on-chain program'shas_oneconstraint onconfig.creatorthen rejects.Impact
Any caller that follows the tool's own instructions (omit
creatorWalletwhen unknown) cannot buy anything. In practice this is most callers —creatorWalletis only known if the LLM happens to carry it over from an earliersearch_skillsresult in the same context. This blocks the entire buy flow for any host/agent that doesn't thread that field through by hand.Suggested fix
Either:
configPDA already stores it) whencreatorWalletis omitted, instead of defaulting to the buyer's own address, orsearch_skills/verify_skillalready return the creator address, so the client never needs to supply it.Also worth updating the
buy_skilltool description, since it currently tells the agent to do the one thing that guarantees failure.