Getting Started
Read Agent Data
Last updated July 8, 2026
Read and verify agent identity after registration — directly on-chain with the SDK, or through the indexed DAS API.
Summary
Agent identity is read on-chain with the Agent Registry SDK or from indexed fields via the DAS API.
- On-chain (SDK) — check registration, inspect the
AgentIdentityplugin, fetch the ERC-8004 document, derive the Asset Signer PDA - Indexed (DAS) — read
is_agent,asset_signer, andagent_tokenfromgetAsset; discover agents withsearchAssets - Same wallet address —
findAssetSignerPdaand DASasset_signerreturn the same PDA
Quick Start
This page covers SDK registration checks, registration documents, wallet PDAs, and DAS-indexed agent fields.
Jump to: Check Registration · Registration Document · Agent Wallet · Read via DAS
- One agent, full detail — use
safeFetchAgentIdentityV1andfetchAsset(SDK sections below) - One agent, indexed fields — call
getAssetwith the Core asset address (DAS section below) - Discover agents — call
searchAssetswithisAgent: trueor filter byagentToken/assetSigner
Check Registration
The safe fetch method returns null instead of throwing if the identity doesn't exist, which is useful for checking whether an asset has been registered:
1import {
2 safeFetchAgentIdentityV1,
3 findAgentIdentityV1Pda,
4 mplAgentIdentity,
5} from '@metaplex-foundation/mpl-agent-registry'
6import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
7import { publicKey } from '@metaplex-foundation/umi'
8
9const umi = createUmi('https://api.mainnet-beta.solana.com').use(mplAgentIdentity())
10const assetPublicKey = publicKey('AGENT_CORE_ASSET_ADDRESS')
11
12const pda = findAgentIdentityV1Pda(umi, { asset: assetPublicKey })
13const identity = await safeFetchAgentIdentityV1(umi, pda)
14
15console.log('Registered:', identity !== null)
16
17// Registered: true
Fetch from Seeds
You can also fetch the identity directly from the asset's public key without manually deriving the PDA:
1import {
2 fetchAgentIdentityV1FromSeeds,
3 mplAgentIdentity,
4} from '@metaplex-foundation/mpl-agent-registry'
5import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
6import { publicKey } from '@metaplex-foundation/umi'
7
8const umi = createUmi('https://api.mainnet-beta.solana.com').use(mplAgentIdentity())
9const assetPublicKey = publicKey('AGENT_CORE_ASSET_ADDRESS')
10
11// Throws if the identity account does not exist — use safeFetchAgentIdentityV1 for unregistered assets.
12const identity = await fetchAgentIdentityV1FromSeeds(umi, {
13 asset: assetPublicKey,
14})
15
16console.log('Identity:', identity)
17
18// Identity: { ... }
Verify the AgentIdentity Plugin
Registration attaches an AgentIdentity plugin to the Core asset. You can read it directly off the fetched asset to inspect the registration URI and lifecycle hooks:
1import { fetchAsset, mplCore } from '@metaplex-foundation/mpl-core'
2import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
3import { publicKey } from '@metaplex-foundation/umi'
4
5const umi = createUmi('https://api.mainnet-beta.solana.com').use(mplCore())
6const assetPublicKey = publicKey('AGENT_CORE_ASSET_ADDRESS')
7
8const assetData = await fetchAsset(umi, assetPublicKey)
9const agentIdentity = assetData.agentIdentities?.[0]
10
11console.log(agentIdentity?.uri)
12console.log(agentIdentity?.lifecycleChecks?.transfer)
13console.log(agentIdentity?.lifecycleChecks?.update)
14console.log(agentIdentity?.lifecycleChecks?.execute)
15
16// https://example.com/agent-registration.json
17// { __kind: 'Listen' }
18// { __kind: 'Listen' }
19// { __kind: 'Listen' }
Read the Registration Document
The uri on the AgentIdentity plugin points to an off-chain JSON document with the agent's full profile — name, description, service endpoints, and more. Fetch it like any other URI:
1import { fetchAsset, mplCore } from '@metaplex-foundation/mpl-core'
2import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
3import { publicKey } from '@metaplex-foundation/umi'
4
5const umi = createUmi('https://api.mainnet-beta.solana.com').use(mplCore())
6const assetPublicKey = publicKey('AGENT_CORE_ASSET_ADDRESS')
7
8const assetData = await fetchAsset(umi, assetPublicKey)
9const agentIdentity = assetData.agentIdentities?.[0]
10
11if (agentIdentity?.uri) {
12 const response = await fetch(agentIdentity.uri)
13 if (!response.ok) {
14 throw new Error(`Registration document fetch failed: HTTP ${response.status}`)
15 }
16 const registration = await response.json()
17
18 console.log(registration.name)
19 console.log(registration.description)
20 console.log(registration.active)
21
22 for (const service of registration.services ?? []) {
23 console.log(service.name)
24 console.log(service.endpoint)
25 console.log(service.version)
26 }
27}
28
29// Plexpert
30// An informational agent...
31// true
32// web
33// https://metaplex.com/agent/<ASSET_PUBKEY>
34// undefined
The document follows the ERC-8004 agent registration standard. A typical one looks like this:
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "An informational agent providing help related to Metaplex protocols and tools.",
"description": "An autonomous agent that executes DeFi strategies on Solana.",
"image": "https://arweave.net/agent-avatar-tx-hash",
"services": [
{
"name": "web",
"endpoint": "https://metaplex.com/agent/<ASSET_PUBKEY>"
},
{
"name": "A2A",
"endpoint": "https://metaplex.com/agent/<ASSET_PUBKEY>/agent-card.json",
"version": "0.3.0"
}
],
"active": true,
"registrations": [
{
"agentId": "<MINT_ADDRESS>",
"agentRegistry": "solana:101:metaplex"
}
],
"supportedTrust": ["reputation", "crypto-economic"]
}
See Register an Agent for the full field reference.
Fetch the Agent's Wallet
Every Core asset has a built-in wallet called the Asset Signer — a PDA derived from the asset's public key. No private key exists, so it can't be stolen. The wallet can hold SOL, tokens, or any other asset. Derive the address with findAssetSignerPda:
1import { findAssetSignerPda, mplCore } from '@metaplex-foundation/mpl-core'
2import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
3import { publicKey } from '@metaplex-foundation/umi'
4
5const umi = createUmi('https://api.mainnet-beta.solana.com').use(mplCore())
6const assetPublicKey = publicKey('AGENT_CORE_ASSET_ADDRESS')
7
8const assetSignerPda = findAssetSignerPda(umi, { asset: assetPublicKey })
9const balance = await umi.rpc.getBalance(assetSignerPda)
10
11console.log('Agent wallet:', assetSignerPda)
12console.log('Balance:', balance.basisPoints.toString(), 'lamports')
13
14// Agent wallet: 6ttUwc5VVmHeVKTddB6XM5vQgBMfw62DThuoiVEufVZq
15// Balance: 1000000 lamports
The address is deterministic, so anyone can derive it from the asset's public key to send funds or check balances. Only the asset itself can sign for this wallet, through Core's Execute instruction via a delegated executive.
See the MPL Agent Registry smart contract docs for account layouts, PDA derivation details, and error codes.
Read Agent Data via DAS API
The DAS API indexes agent fields on MPL Core assets — registration status, wallet PDA, and canonical token mint — so you can read them without parsing Core accounts yourself.
Prerequisites: a DAS-enabled RPC endpoint and @metaplex-foundation/digital-asset-standard-api on a Umi instance.
DAS Agent Response Fields
DAS derives agent metadata from two on-chain sources and surfaces them as top-level response fields.
| Field | Type | Present on | Source |
|---|---|---|---|
is_agent | boolean | MplCoreAsset | true when the asset has an AgentIdentity external plugin |
asset_signer | string (pubkey) | MplCoreAsset only | Same PDA as findAssetSignerPda above |
agent_token | string (pubkey) | MplCoreAsset when set | AgentIdentityV2 PDA mint, written by setAgentTokenV1 |
Only MplCoreAsset rows can be agents (is_agent: true). Collections and groups may include is_agent: false in DAS responses, but agent registration applies to individual Core assets only. Non-Core assets (Token Metadata NFTs, compressed NFTs, fungible tokens) omit all three fields.
A registered agent without a linked token returns is_agent: true and asset_signer, but omits agent_token:
{
"interface": "MplCoreAsset",
"id": "84jw9dw7hMRJXFvzJXrBzVQpmVWaGUtYT7R6QhNU9qt3",
"is_agent": true,
"asset_signer": "6ttUwc5VVmHeVKTddB6XM5vQgBMfw62DThuoiVEufVZq",
"external_plugins": [
{
"type": "AgentIdentity",
"adapter_config": { "uri": "https://example.com/agent-registration.json" }
}
]
}
After setAgentTokenV1, DAS includes agent_token:
{
"interface": "MplCoreAsset",
"id": "84jw9dw7hMRJXFvzJXrBzVQpmVWaGUtYT7R6QhNU9qt3",
"is_agent": true,
"agent_token": "FakeToken11111111111111111111111111111111111",
"asset_signer": "6ttUwc5VVmHeVKTddB6XM5vQgBMfw62DThuoiVEufVZq"
}
JSON-RPC responses use snake_case (is_agent, agent_token, asset_signer). searchAssets request parameters use camelCase (isAgent, agentToken, assetSigner); snake_case aliases are also accepted.
Get One Agent via DAS
Use getAsset when you know the Core asset address.
1import { dasApi } from '@metaplex-foundation/digital-asset-standard-api'
2import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
3import { publicKey } from '@metaplex-foundation/umi'
4
5const umi = createUmi('<DAS_ENDPOINT>').use(dasApi())
6
7const asset = await umi.rpc.getAsset(publicKey('AGENT_CORE_ASSET_ADDRESS'))
8
9if (asset.is_agent) {
10 console.log('Agent wallet (asset_signer):', asset.asset_signer)
11 console.log('Canonical token mint:', asset.agent_token ?? 'not set')
12} else {
13 console.log('Core asset is not a registered agent')
14}
15
16// Agent wallet (asset_signer): 6ttUwc5VVmHeVKTddB6XM5vQgBMfw62DThuoiVEufVZq
17// Canonical token mint: not set
1curl -X POST <DAS_ENDPOINT> \
2 -H "Content-Type: application/json" \
3 -d '{
4 "jsonrpc": "2.0",
5 "id": 1,
6 "method": "getAsset",
7 "params": { "id": "AGENT_CORE_ASSET_ADDRESS" }
8 }'
Search Registered Agents
Use searchAssets with isAgent: true to list registered agents. Combine with interface: "MplCoreAsset" to exclude collections and groups.
1import { dasApi } from '@metaplex-foundation/digital-asset-standard-api'
2import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
3
4const umi = createUmi('<DAS_ENDPOINT>').use(dasApi())
5
6const results = await umi.rpc.searchAssets({
7 isAgent: true,
8 interface: 'MplCoreAsset',
9 limit: 100,
10})
11
12for (const agent of results.items) {
13 console.log(agent.id, agent.asset_signer, agent.agent_token ?? 'no token')
14}
15
16// 1RUC5FMQherGNoLF9wDBxa1oznbq1mTieWLZ8gU8S31 DwgDrVVwcuXGU2MjHcZEcNtG2cGF6cLXCS35gPiUsU6p no token
1curl -X POST <DAS_ENDPOINT> \
2 -H "Content-Type: application/json" \
3 -d '{
4 "jsonrpc": "2.0",
5 "id": 1,
6 "method": "searchAssets",
7 "params": {
8 "isAgent": true,
9 "interface": "MplCoreAsset",
10 "limit": 100
11 }
12 }'
Lookup Agent by Token Mint
After an agent links its canonical token, filter by agentToken to resolve the agent Core asset from the mint address. Each agent can have at most one token — the binding is permanent.
1curl -X POST <DAS_ENDPOINT> \
2 -H "Content-Type: application/json" \
3 -d '{
4 "jsonrpc": "2.0",
5 "id": 1,
6 "method": "searchAssets",
7 "params": {
8 "agentToken": "TOKEN_MINT_ADDRESS",
9 "interface": "MplCoreAsset",
10 "limit": 1
11 }
12 }'
Lookup Agent by Asset Signer
The assetSigner filter finds the Core asset whose execute PDA matches a given address. Use this when you know the agent wallet but not the asset pubkey.
1curl -X POST <DAS_ENDPOINT> \
2 -H "Content-Type: application/json" \
3 -d '{
4 "jsonrpc": "2.0",
5 "id": 1,
6 "method": "searchAssets",
7 "params": {
8 "assetSigner": "ASSET_SIGNER_PDA_ADDRESS",
9 "limit": 1
10 }
11 }'
How DAS Indexing Works
DAS populates agent fields from two on-chain sources during ingestion. MPL Core asset account updates set is_agent (when an AgentIdentity plugin is present) and derive asset_signer for MplCoreAsset rows. Agent Registry PDA updates set agent_token on existing MplCoreAsset rows when an AgentIdentityV2 mint is present.
| Event | Field updated | Notes |
|---|---|---|
| Core asset created or updated | is_agent, asset_signer | Applies to MplCoreAsset rows only; is_agent reflects the AgentIdentity external plugin; asset_signer is derived for every indexed Core asset |
AgentIdentityV2 PDA updated | agent_token | Written by the Agent Registry transformer; only updates existing, non-burnt MplCoreAsset rows |
| Asset burnt | — | Subsequent Agent Registry updates are ignored |
| Stale-slot PDA replay | — | Updates with a lower slot than slot_updated_agent_registry are skipped |
Notes
- The Asset Signer is a PDA — no private key exists for it. It can receive funds from any source, but only the asset itself can sign outgoing transactions through Core's Execute instruction.
safeFetchAgentIdentityV1returnsnullfor unregistered assets rather than throwing, making it safe for existence checks without try/catch.findAssetSignerPdaand DASasset_signerreturn the same deterministic address on every network.agent_tokenis permanent once set viasetAgentTokenV1— there is no instruction to clear or reassign it.- DAS
asset_signeris returned onMplCoreAssetrows, not only registered agents; useis_agentto distinguish agents from plain Core NFTs. - Registered agents without a linked token omit
agent_token— expected beforecreateAndRegisterLaunchor manualsetAgentTokenV1. - Agent Registry updates never create new asset rows; the Core asset must be indexed first.
- Provider support varies — confirm your DAS provider runs an indexer with agent registry support.
Quick Reference
This table lists agent-related DAS filters, response fields, and program IDs.
| Item | Value |
|---|---|
| Agent Registry program | 1DREGFgysWYxLnRnKQnwrxnJQeSMk2HmGaC6whw2B2p |
| MPL Core program | CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d |
| Asset Signer seeds | ['mpl-core-execute', <core_asset_pubkey>] |
DAS isAgent filter | searchAssets param isAgent: true | false |
DAS agentToken filter | searchAssets param agentToken: <mint_pubkey> |
DAS assetSigner filter | searchAssets param assetSigner: <pda_pubkey> |
| DAS response methods | getAsset, getAssets, searchAssets |
FAQ
When does agentToken appear in a DAS response?
agent_token is present only when the agent's AgentIdentityV2 PDA has a token mint set via setAgentTokenV1. Registered agents without a linked token omit the field. AgentIdentityV1 PDAs do not carry a token mint and never populate agent_token.
Is assetSigner the same as the agent wallet?
Yes. DAS asset_signer is the Core Asset Signer PDA — the same address as findAssetSignerPda. It is returned on MplCoreAsset rows; for registered agents it acts as the on-chain wallet.
Can I filter non-Core assets with isAgent?
No. is_agent, agent_token, and asset_signer apply only to MplCoreAsset. Token Metadata NFTs and other asset types omit these fields.
Do all DAS providers support agent token fields?
Agent token indexing ships with the Metaplex DAS indexer. Third-party providers must run a compatible indexer version with the agent registry transformer and database migration.
Glossary
These terms appear in agent DAS responses and the SDK read paths above.
| Term | Definition |
|---|---|
AgentIdentity plugin | External plugin on a Core asset set during registration; carries the off-chain registration URI |
is_agent | DAS boolean indicating the Core asset has an AgentIdentity external plugin |
agent_token | Canonical token mint pubkey indexed from the AgentIdentityV2 PDA; set once via setAgentTokenV1 |
asset_signer | Core execute PDA that acts as the agent's onchain wallet; derived from ['mpl-core-execute', <asset>] |
AgentIdentityV2 | Agent Registry PDA that stores the linked token mint; updated independently of the Core asset account |
Agent Registry transformer | DAS ingestion handler that writes agent_token from Agent Registry PDA updates onto existing Core asset rows |
