Publishing an agent
Publishing does two things: it puts your code somewhere content addressed, and it puts a signed claim in the index that says "this public key published this code, under this description, in this asset class". This page walks the flow in order, and explains why each part is shaped the way it is.
Start at dashboard/upload. Your vault must be unlocked, because the browser needs your private key in memory to sign.
Step 1. The code goes to IPFS
You select the agent's source files. The browser posts them to the Wakehood server, which forwards them to IPFS and returns a content identifier (CID).
The upload runs server side rather than directly from the browser so that the IPFS credential is never exposed to a client. That is the only reason it passes through us. The bytes are stored and addressed. They are not inspected, not interpreted, and not run.
A CID is a hash of the content. The same files always produce the same CID, and different files always produce a different one. This matters for the next step.
Limits
| Limit | Value |
|---|---|
| Maximum files per upload | 100 |
| Maximum total size | 10 MB |
| Name (agent) | 80 characters |
| Description | 2,000 characters |
| Strategy tags | At least one, all within the asset class taxonomy |
These are hard limits enforced by the server. An upload over the file count returns a 413, and so does one over the size cap. Ten megabytes is generous for strategy source. If your agent needs more than that, you are shipping model weights or data, which belong somewhere else.
Step 2. The metadata is signed in your browser
Once you have a CID, your browser assembles the agent metadata:
{
"name": "Momentum Rotator",
"description": "Ranks tokenized sector ETFs by 20 day momentum and rotates weekly.",
"assetType": "ETF",
"tags": ["sector rotation", "ETF rebalancing"],
"ipfsCid": "bafybei..."
}
It then signs a canonical message built from four things:
POST
/api/agents
1768435200000
{"assetType":"ETF","description":"...","ipfsCid":"bafybei...","name":"...","tags":[...]}
That is the HTTP method, the request path, a millisecond timestamp, and the body serialised with
sorted keys. Sorting the keys is not cosmetic: plain JSON.stringify preserves insertion order,
so the client and the server could otherwise hash different bytes for the same logical object and
every signature would fail at random.
The Ed25519 signature over that message is sent alongside your public key and the timestamp. Your private key never leaves the browser.
Why the CID is inside the signed payload
Because the signature then covers exactly the code being published, not just its title.
If the CID were outside the signature, or attached afterwards by the server, an attacker who could tamper with the request in flight could keep your name, your description, and your signature, and swap in a CID pointing at entirely different code. Your identity would be vouching for something you never uploaded.
By hashing the CID into the signed message, the claim becomes atomic and specific: this key published this exact content under this exact description. Change one byte of the code and the CID changes, which changes the message, which invalidates the signature. There is no way to substitute the payload without breaking the proof.
Step 3. The server verifies
The server trusts nothing in the request until the signature checks out. In order:
- Signature. It rebuilds the same canonical message from the method, path, timestamp, and
body it actually received, and verifies the Ed25519 signature against the supplied public key.
Any mismatch is a
401. - Freshness. The timestamp must be within 2 minutes of the server's clock, in either direction. Absolute value, so a fast clock cannot mint far-future requests either. This bounds replay: a captured request stops working almost immediately. If your machine's clock is badly wrong, publishing will fail with an expiry error, and the fix is to correct your clock.
- Asset class.
assetTypemust be one ofCRYPTO,STOCK,ETF,MIXED. Anything else is a400. - Taxonomy. Tags are checked against the strategy tags allowed for that asset class. Tags
outside it are not accepted, and if nothing valid remains the publish is rejected with "select
at least one strategy tag for this asset class". You cannot invent a tag, and a
STOCKagent cannot claimyield farming. See asset classes and strategies. - Ownership. The owner recorded on the agent is the public key that signed the request, never a public key supplied in the body. There is no way to publish an agent under someone else's name, because doing so would require their private key.
If all of that passes, the agent is written to the index and returned with a 201.
Step 4. It appears in the index
The agent is now visible in Explore, filterable by asset class and strategy tag, and
on your profile at /profile/<your public key>. Its detail page shows the description, the tags,
the owner, and the IPFS CID, with a gateway link so that anyone can fetch and read the code you
published.
Your trust score increases by 10. That reflects that you published, and nothing more.
Mock IPFS mode
Wakehood uses Pinata to pin files to IPFS. If a deployment has no PINATA_JWT configured, the
IPFS layer runs in mock mode instead of failing.
In mock mode, the server hashes the actual file bytes and derives a deterministic,
CID-shaped string (bafybei...) from that fingerprint. The same files always produce the same
mock CID, so the entire flow, publish through detail page through copy-to-clipboard, behaves
exactly as it will in production, and the signing model is unchanged.
Be clear about what this is:
- A mock CID is not on the public IPFS network. Nothing was pinned. Nothing was uploaded anywhere.
- Fetching a mock CID from a public gateway will not return your code, because your code is not there.
- It is a development and demonstration mode, not a storage backend.
The moment a real PINATA_JWT is configured, uploads become real with no change to the client,
the signature, or the schema. If you are self-hosting Wakehood and you want real storage, provide
the credential.
Wakehood never runs your code
Uploaded agent code is stored and indexed. It is never executed by Wakehood: not in a sandbox, not on a schedule, not on your behalf, not on anyone's behalf. Phase 1 is a hosting and discovery platform, and running untrusted strategy code safely would require an execution sandbox that does not exist here.
The direct consequence for anyone browsing the index: nothing on this platform has been run, tested, audited, or verified by us. A listing means someone with a keypair uploaded some files and described them. If you intend to run an agent you found here, read the code first, understand what it does with your keys and your funds, and run it under your own risk controls. Nothing on Wakehood is investment advice.
After publishing
Phase 1 has no delete or edit for a published agent. Beyond that, IPFS is content addressed: once content has been pinned and fetched, copies can persist independently of any index we control. Do not publish anything you would need to be able to retract, and do not put secrets, API keys, or credentials in the files you upload. See the FAQ for the honest version of this.