For AI agents: Documentation index at /llms.txt

Skip to content

Application canisters

Application canisters are well-known canisters at the application layer of the Internet Computer that developers commonly integrate into their projects. Unlike system canisters (which govern the network) or protocol canisters (which provide platform infrastructure), application canisters implement higher-level functionality: hosting web frontends, governing apps via DAO, and running AI inference.

The certified-assets canister hosts static web assets (HTML, CSS, JavaScript, images, and other files) directly on the network. The @dfinity/static-site recipe deploys it, and it is the recommended way to host a frontend on ICP. Every response it serves is certified, and it accepts only version 2 of the certification protocol, so it has no uncertified serving path. Whether a visitor gets a verified response is a separate question, decided by the gateway their URL points at: see Certified vs uncertified access.

These canisters are deployed per-project. There is no global canister ID: each project creates its own.

canisters:
- name: frontend
recipe:
type: "@dfinity/static-site@v0.3.3"
configuration:
dir: dist
build:
- npm install
- npm run build

The recipe pins a matched canister and sync-plugin pair, so the recipe version is the canister version: there is no separate configuration.version field. See Hosting a static site for the remaining configuration fields.

MethodDescription
version()The release identity shared by the canister and its sync plugin
http_request(req)Serve an HTTP request with a certified response
get_asset_details(start_after)A page of asset details, ordered by key
get_redirect_rules(start_index)A page of redirect rules, in match order

Sync. Assets are only ever mutated through a sync, and at most one sync runs at a time. start_sync returns a session id that every later call must carry.

MethodDescription
start_sync()Begin a sync, or report Busy
upload_chunks(arg)Stage content chunks under the sync
execute_operations(arg)Apply a group of operations; the call flagged is_final finalizes the sync and returns the new state hash
preparation_canary()The compression fingerprint of the client that last prepared the assets

Authorization. Controllers are always authorized without being listed, and are the only callers that can change the set.

MethodDescription
authorize(principal)Allow a principal to sync assets
deauthorize(principal)Revoke that permission
list_authorized()The extra principals authorized to sync
can_sync()Whether the caller may sync

Verification and environment:

MethodDescription
state_hash()The canonical 32-byte hash over the served-content model, recomputed at the end of every sync. An update call, so the reply is consensus-backed
refresh_env()Re-capture PUBLIC_* variables and the root key, and re-certify the ic_env cookie

Access protection (controller-only, for private and preview sites):

MethodDescription
enable_protection(login_page)Turn the gate on, naming the login page asset
disable_protection()Turn the gate off and drop all tokens
issue_token(arg)Mint an access token, returned once
revoke_token(label)Revoke the tokens with that label
list_tokens()Live tokens with their expiry
check_protection_status()Whether protection is off, healthy, or degraded

Two files at the root of dir configure the canister, and are read as configuration rather than served: _redirects for SPA fallback, redirects, rewrites, and error pages, and _headers for caching, security headers, and media types. No headers are applied by default. See Redirects and rewrites and Custom headers.

There is no per-asset write endpoint and no JS equivalent of AssetManager. Uploads go through the recipe’s sync plugin on icp deploy, because finalizing a sync recomputes the whole-site state_hash that makes a build provable. Apps with user-generated content should store it in a separate canister.


The asset canister is the older SDK canister for hosting static web assets, deployed by the @dfinity/asset-canister recipe and configured with .ic-assets.json5. It remains supported for existing projects; new projects should use the certified-assets canister above, with one exception: proposal-gated asset updates for an SNS-governed frontend exist only here, through propose_commit_batch and the Prepare/Commit permission split. Responses are certified by the subnet, allowing HTTP gateways to verify integrity before serving content to browsers.

Asset canisters are deployed per-project. There is no global asset canister ID: each project creates its own.

canisters:
- name: frontend
recipe:
type: "@dfinity/asset-canister@v2.3.0"
configuration:
dir: dist
build:
- npm install
- npm run build
  • recipe.type: identifies this as an asset canister deployment
  • dir: the build output directory whose contents are uploaded
  • build: commands run automatically by icp deploy before uploading

The asset canister exposes the following Candid methods:

Permission management:

MethodDescription
grant_permission(arg)Grant a principal a permission role (Prepare, Commit, or ManagePermissions)
revoke_permission(arg)Revoke a permission role from a principal
list_permitted(arg)Query principals with a given permission role
take_ownership()Caller becomes the sole authorized principal

Asset operations:

MethodDescription
store(arg)Upload a single asset in one call
create_batch()Begin a chunked upload batch
create_chunk(arg)Upload a chunk of a large asset
commit_batch(arg)Finalize a batch and make assets live
create_asset(arg)Create an asset entry without uploading content
set_asset_content(arg)Set or replace the content of an asset
unset_asset_content(arg)Remove content encoding from an asset
delete_asset(arg)Delete an asset
clear()Remove all assets from the canister

Asset queries:

MethodDescription
retrieve(key)Fetch raw asset bytes by key
get(arg)Fetch an asset with encoding and metadata
get_chunk(arg)Fetch a specific chunk of a large asset
list()List all uploaded assets with metadata
get_asset_properties(key)Query per-asset headers and aliasing settings
set_asset_properties(arg)Set per-asset headers and aliasing
certified_tree()Return the certificate tree for response verification

HTTP serving:

MethodDescription
http_request(req)Serve an HTTP request with certified response
http_request_streaming_callback(token)Stream large responses in chunks

Create .ic-assets.json5 in your dir directory (or public//static/ so your build copies it):

[
{
"match": "**/*",
"security_policy": "standard",
"headers": {
"Cache-Control": "public, max-age=0, must-revalidate"
},
"allow_raw_access": false
},
{
"match": "assets/**/*",
"headers": {
"Cache-Control": "public, max-age=31536000, immutable"
}
},
{
"match": "**/*",
"enable_aliasing": true
}
]
  • security_policy: "standard": applies the default Content Security Policy and security headers
  • allow_raw_access: false: disables serving assets on the uncertified raw.icp.net domain
  • enable_aliasing: true: enables SPA fallback, serving index.html for unmatched paths

Specific to this canister, and not a recommended pattern: see Asset canister (legacy). @icp-sdk/canisters (>= 3.5.0) uploads assets from code:

import { AssetManager } from "@icp-sdk/canisters/assets";
import { HttpAgent } from "@icp-sdk/core/agent";
const agent = await HttpAgent.create({
host: "https://ic0.app",
shouldFetchRootKey: false, // never fetch root key against mainnet
});
const assetManager = new AssetManager({
canisterId: "your-asset-canister-id",
agent,
});
// Upload a file (files >1.9MB are chunked automatically)
// fileBuffer: Uint8Array | ArrayBuffer | number[]: e.g. from fs.readFileSync, fetch, or the File API
await assetManager.store(fileBuffer, {
fileName: "photo.jpg",
contentType: "image/jpeg",
path: "/uploads",
});
// List all assets
const assets = await assetManager.list();
// Delete an asset
await assetManager.delete("/uploads/old-photo.jpg");

The asset canister Wasm version determines which features are available. Key versions:

  • 0.30.2+: required for the ic_env cookie (used by safeGetCanisterEnv() from @icp-sdk/core)
  • Omitting configuration.version in the recipe uses the latest version automatically

Downgrading the Wasm version may fail if the stable memory format changed between versions. If a downgrade is necessary, use icp deploy --mode reinstall (wipes all stored assets).

For version history, upgrade guidance, and deployment pitfalls, see Asset canister (legacy).


When an SNS (Service Nervous System) is launched for an app, the SNS-W canister deploys a set of governance canisters on an SNS subnet. These canisters are created per-app: there is no single global SNS. To find the canister IDs for a specific SNS, look up the app on the ICP Dashboard.

CanisterPurpose
GovernanceProposal submission, voting, neuron management
LedgerSNS token transfers (ICRC-1 standard)
RootSole controller of all app canisters post-launch
SwapRuns the decentralization swap (ICP for SNS tokens)
IndexTransaction indexing for the SNS ledger
ArchiveHistorical transaction storage

The governance canister is the primary interface for SNS operations:

MethodDescription
manage_neuronCreate, configure, or vote with a neuron
get_neuronQuery a neuron’s state and voting power
list_neuronsList neurons for a principal
get_proposalQuery a proposal
list_proposalsList proposals with filtering
get_nervous_system_parametersQuery the current governance parameters
get_metadataQuery the SNS name, description, and logo

The SNS ledger implements ICRC-1, ICRC-2, and ICRC-3. The key methods are the same as any ICRC-1 ledger:

MethodDescription
icrc1_transferTransfer SNS tokens
icrc1_balance_ofQuery an account balance
icrc1_total_supplyQuery the total token supply
icrc2_approveApprove a spender
icrc2_transfer_fromTransfer on behalf of an approver
icrc3_get_blocksQuery transaction history (ICRC-3 transaction log)

For ICRC interface details, see Digital Asset Standards.

After an SNS is launched, call the list_sns_canisters method on the Root canister to retrieve the IDs of all canisters in the set:

Terminal window
icp canister call <sns_root_id> list_sns_canisters '()' -e ic
# Returns: record { root: principal; swap: principal; ledger: principal; index: principal; governance: principal; dapps: vec principal; archives: vec principal }

For SNS launch configuration and governance setup, see Launching an SNS.


The LLM canister provides AI inference running on the network, using large language models, enabling canisters to generate text, run chat completions, and build AI agents without external API keys.

FieldValue
Canister IDw36hm-eqaaa-aaaal-qr76a-cai
Candid interfacellm-canister-ollama.did
ModelIdentifier
Llama 3.1 8BLlama3_1_8B

Add the ic-llm crate to your project:

[dependencies]
ic-cdk = "0.17"
ic-llm = "1.1.0"

Single-turn prompt:

use ic_cdk::update;
use ic_llm::{ChatMessage, Model};
#[update]
async fn prompt(prompt_str: String) -> String {
ic_llm::prompt(Model::Llama3_1_8B, prompt_str).await
}

Multi-turn chat:

use ic_cdk::update;
use ic_llm::{ChatMessage, Model};
#[update]
async fn chat(messages: Vec<ChatMessage>) -> String {
let response = ic_llm::chat(Model::Llama3_1_8B)
.with_messages(messages)
.send()
.await;
response.message.content.unwrap_or_default()
}

Add the llm package to your mops.toml:

[dependencies]
llm = "2.1.0"

Single-turn prompt:

import LLM "mo:llm";
persistent actor {
public func prompt(prompt : Text) : async Text {
await LLM.prompt(#Llama3_1_8B, prompt);
};
};

Multi-turn chat:

import LLM "mo:llm";
persistent actor {
public func chat(messages : [LLM.ChatMessage]) : async Text {
let response = await LLM.chat(#Llama3_1_8B).withMessages(messages).send();
switch (response.message.content) {
case (?text) text;
case null "";
};
};
};

The LLM canister requires an Ollama server for local testing:

Terminal window
# Start the Ollama server
ollama serve
# Pull the model (one-time download, ~4 GiB)
ollama pull llama3.1:8b

icp-cli does not yet have an equivalent of dfx’s "type": "custom" / "remote" canister configuration for pointing a local replica at the Ollama-backed LLM Wasm. To test the LLM canister locally, use the example project from dfinity/examples which includes the dfx.json configuration needed for this setup.

For a complete guide, see AI inference.


CanisterCanister IDPurpose
Certified-assetsPer-projectStatic web asset hosting, every response certified
Asset canister (legacy)Per-projectStatic web asset hosting with HTTP certification
SNS governancePer-appDAO governance for a specific app
SNS ledgerPer-appICRC-1/ICRC-2/ICRC-3 token ledger for a specific SNS
SNS rootPer-appController of all app canisters in the SNS set
SNS swapPer-appDecentralization swap (ICP for SNS tokens)
LLMw36hm-eqaaa-aaaal-qr76a-caiOnchain AI inference (Llama 3.1 8B)