Skip to content

nais-standard/nais-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

NAIS Python SDK

Python SDK for the Network Agent Identity Standard (NAIS).

NAIS lets AI agents publish discoverable identities via DNS TXT records and .well-known/agent.json manifests. Each agent exposes an MCP (Model Context Protocol) endpoint that speaks JSON-RPC 2.0, making it straightforward for any client to find and call agent tools.

This SDK handles the full workflow: resolve a domain, inspect the manifest, and invoke tools -- in three lines of code.

Installation

pip install nais-sdk

Quick Start

import nais

# Resolve an agent by domain
agent = nais.resolve("weatheragent.nais.id")

print(agent.name)               # "Weather Agent"
print(agent.get_endpoint())     # "https://weatheragent.nais.id/mcp"
print(agent.get_capabilities()) # [{"name": "forecast", ...}]

# Invoke a tool
result = agent.invoke("forecast", {"city": "New York"})
print(result)

API Reference

Module-Level Functions

nais.resolve(domain, resolver_url=None, timeout=10) -> NaisAgent

Resolve a NAIS domain and return a NaisAgent object. Uses the public resolver at https://resolver.nais.id/resolve.php by default.

agent = nais.resolve("weatheragent.nais.id")

nais.get_manifest(domain, timeout=10) -> dict

Convenience function that resolves a domain and returns just the manifest data dictionary.

manifest = nais.get_manifest("weatheragent.nais.id")
print(manifest["name"])  # "Weather Agent"

nais.validate_manifest(manifest) -> dict

Validate a manifest dictionary. Returns {"valid": True/False, "errors": [...]}.

result = nais.validate_manifest(manifest)
if not result["valid"]:
    print("Errors:", result["errors"])

nais.invoke(endpoint, method, params=None, headers=None, timeout=30) -> any

Low-level function to invoke an MCP tool directly by endpoint URL. Sends a JSON-RPC 2.0 tools/call request.

result = nais.invoke("https://weatheragent.nais.id/mcp", "forecast", {"city": "NYC"})

NaisAgent

Returned by nais.resolve(). Wraps the resolver response with convenient accessors.

Property / Method Returns Description
agent.domain str Agent domain name
agent.name str Human-readable name
agent.description str | None Agent description
agent.raw_response dict Full resolver JSON
agent.get_manifest() dict | None Parsed manifest data
agent.get_endpoint() str | None MCP endpoint URL
agent.get_capabilities() list[dict] Advertised capabilities
agent.get_capability(name) dict | None Single capability by name
agent.get_auth_methods() list[str] Supported auth methods
agent.get_payment_methods() list[str] Supported payment methods
agent.requires_auth() bool True if "none" is not in auth methods
agent.has_free_tier() bool True if a free tier is available
agent.get_wallet() str | None Wallet address
agent.invoke(method, params=None, headers=None, timeout=30) any Invoke an MCP tool

NaisClient

For repeated calls, NaisClient reuses an HTTP session for better performance.

from nais import NaisClient

client = NaisClient()
agent = client.resolve("weatheragent.nais.id")
result = client.invoke("weatheragent.nais.id", "forecast", {"city": "NYC"})
Method Returns Description
client.resolve(domain) NaisAgent Resolve a domain
client.get_manifest(domain) dict Get manifest data
client.invoke(domain, method, params=None, headers=None, timeout=30) any Resolve + invoke in one call

Exceptions

All exceptions inherit from NaisError.

Exception When
NaisError Base class for all SDK errors
ResolveError Domain resolution fails
ManifestError Manifest fetch/validation fails
InvokeError MCP invocation fails (has .response_data attribute)
from nais import ResolveError

try:
    agent = nais.resolve("nonexistent.example.com")
except ResolveError as e:
    print(f"Resolution failed: {e}")

Authentication and Payment

NAIS agents declare their supported auth and payment methods in their manifest.

agent = nais.resolve("weatheragent.nais.id")

if agent.requires_auth():
    # Pass auth headers when invoking
    result = agent.invoke("forecast", {"city": "NYC"}, headers={
        "Authorization": "Bearer <token>"
    })
else:
    result = agent.invoke("forecast", {"city": "NYC"})

if agent.has_free_tier():
    print("This agent has a free tier!")

print("Auth methods:", agent.get_auth_methods())      # ["wallet", "none"]
print("Payment methods:", agent.get_payment_methods()) # ["x402", "free"]

Version 1 Limitations

  • HTTP-only MCP transport: The SDK calls MCP endpoints over HTTP POST. Streaming and WebSocket transports are not yet supported.
  • No automatic auth flows: The SDK does not handle wallet-based signing or token exchange. You must supply auth headers manually.
  • No retry/backoff: Failed requests are not retried. Implement retries in your own code if needed.
  • Resolver dependency: Resolution relies on the hosted resolver at resolver.nais.id. Direct DNS TXT lookups are not performed client-side.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages