Once a Payment Plan is purchased, user(s) can query all the AI Agents linked to that plan.
For identifying the user as a valid subscriber, they need to send HTTP requests to the AI Agent via a Nevermined Proxy instance and include a valid Access Token . This is sent using the standard HTTP Authorization header .
Nevermined Proxy instances are standard HTTP Proxies in charge of authorizing users trying to access AI Agents or Services.
Once a user is a subscriber, sending a request is quite simple.
Get the AI Agent or Service Access Token
const credentials = await payments . agents . getAgentAccessToken ( planId , agentId )
// OUTPUT: credentials:
// {
// accessToken: 'eJyNj0sKgDAURP9lJQ ....',
// proxies: [ 'https://proxy.nevermined.app' ]
// }
Sending a query to the AI Agent
If the response of the getAgentAccessToken
method contains a valid accessToken
, the user can query the AI Agent making a standard HTTP request.
This request must be sent directly to the Agent (the description of the Agent API is in the Agent Metadata) or if the agentAccessParams
includes an entry in the proxies
array, through one of the Nevermined Proxy instances listed in the proxies
array of the response.
Because Nevermined authorizes standard HTTP requests, they can be used to protect any kind of AI Agent or Service exposing an HTTP API.
Using cURL
export AGENT_ACCESS_TOKEN = "eJyNj0sKgDAURP9lJQ..."
curl -k -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AGENT_ACCESS_TOKEN " \
-d '{"query": "hey there"}' \
https://my.agent.io/prompt
Using Programming Languages
const agentHTTPOptions = {
method: 'POST' ,
headers: {
Accept: 'application/json' ,
'Content-Type' : 'application/json' ,
Authorization: `Bearer ${ credentials . accessToken } ` ,
},
body: JSON . stringify ({
query: "What's the weather like today?" ,
parameters: {
location: "New York"
}
})
}
const response = await fetch ( new URL ( 'https://my.agent.io/prompt' ), agentHTTPOptions )
const result = await response . json ()
console . log ( 'Agent response:' , result )
Complete Query Flow Example
Here’s a complete example showing the full flow from getting access tokens to querying an agent:
async function queryAIAgent ( planId : string , agentId : string , query : string ) {
try {
// Step 1: Get access credentials
const credentials = await payments . agents . getAgentAccessToken ( planId , agentId )
if ( ! credentials . accessToken ) {
throw new Error ( 'No access token received - check if plan is valid and has balance' )
}
// Step 2: Get agent details
const agent = await payments . agents . getAgent ( agentId )
const endpoint = agent . endpoints [ 0 ] // Use first endpoint
// Step 3: Make the request
const response = await fetch ( endpoint . url , {
method: endpoint . method || 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ credentials . accessToken } `
},
body: JSON . stringify ({ query })
})
if ( response . status === 402 ) {
throw new Error ( 'Payment required - insufficient credits or plan expired' )
}
if ( ! response . ok ) {
throw new Error ( `Agent request failed: ${ response . status } ${ response . statusText } ` )
}
const result = await response . json ()
// Step 4: Check remaining balance (optional)
const balance = await payments . plans . getPlanBalance ( planId )
console . log ( `Remaining credits: ${ balance . balance } ` )
return result
} catch ( error ) {
console . error ( 'Query failed:' , error . message )
throw error
}
}
// Usage
const result = await queryAIAgent ( planId , agentId , "Explain quantum computing" )
console . log ( 'AI Response:' , result )
Handling Different Response Types
AI agents can return various types of responses. Here’s how to handle them:
async function handleAgentResponse ( response : Response ) {
const contentType = response . headers . get ( 'content-type' )
if ( contentType ?. includes ( 'application/json' )) {
// JSON response (most common)
return await response . json ()
} else if ( contentType ?. includes ( 'text/' )) {
// Text response
return await response . text ()
} else if ( contentType ?. includes ( 'image/' )) {
// Image response
const blob = await response . blob ()
return URL . createObjectURL ( blob )
} else {
// Binary or other response
return await response . arrayBuffer ()
}
}
Error Handling and Status Codes
Request was successful and credits were deducted from the user’s balance
Invalid or missing access token. User needs to get a new token
User doesn’t have sufficient credits or their plan has expired
User has access but the specific endpoint is not allowed for their plan
Too many requests. User should wait before trying again
Agent internal error. This doesn’t consume credits
Best Practices
Token Management
Cache access tokens (they’re valid for a limited time)
Refresh tokens when they expire
Never expose tokens in client-side logs
Error Handling
Always check response status codes
Implement retry logic for network failures
Handle 402 responses by prompting for plan renewal
Performance
Reuse access tokens across multiple requests
Implement request timeouts
Use appropriate HTTP methods (GET, POST)
Monitoring
Track credit usage patterns
Monitor response times and error rates
Set up alerts for low credit balances
Advanced Usage Patterns
Batch Requests
For efficiency, you can send multiple queries in a single request:
const batchQuery = {
requests: [
{ id: '1' , query: 'What is AI?' },
{ id: '2' , query: 'Explain machine learning' },
{ id: '3' , query: 'Define neural networks' }
]
}
const response = await fetch ( agentEndpoint , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ accessToken } `
},
body: JSON . stringify ( batchQuery )
})
Streaming Responses
For long-running AI operations, you might want to handle streaming responses:
const response = await fetch ( agentEndpoint , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ accessToken } ` ,
'Accept' : 'text/event-stream'
},
body: JSON . stringify ({ query , stream: true })
})
const reader = response . body ?. getReader ()
if ( reader ) {
while ( true ) {
const { done , value } = await reader . read ()
if ( done ) break
const chunk = new TextDecoder (). decode ( value )
console . log ( 'Streaming chunk:' , chunk )
}
}
Next Steps
Now that you know how to query AI agents, learn how to: