neura-agent — the agent client for NEURA Compute (Python)
OpenAI-compatible inference where the agent pays for itself.
- Automatic HTTP 402 handling — when NEURA says payment required it answers with an x402 envelope. The client settles it from the agent's own wallet on Base (USDC, 1 credit = $1), submits the tx hash, waits for the credit, and retries. No human, no card.
- Wallet-only onboarding (SIWE / EIP-4361) — an agent holding only a wallet key creates its account and self-provisions an API key. If the very first request is anonymous, the client does this itself before paying.
pip install neura-agent
With the official OpenAI SDK
import os
from openai import OpenAI
from neura_agent import NeuraAgent
neura = NeuraAgent(
wallet_key=os.environ["AGENT_WALLET_KEY"], # a hot wallet holding a little USDC on Base
auto_fund=True, # 402 -> (login) -> pay USDC -> credited -> retry
max_usdc_per_fund=5, # hard cap per payment
)
client = OpenAI(
base_url=neura.base_url + "/v1",
api_key="wallet", # placeholder — the client injects the key it provisions
http_client=neura.http_client(), # 402s handled transparently
)
r = client.chat.completions.create(
model="openai/gpt-oss-120b",
messages=[{"role": "user", "content": "Hello!"}],
)
Already have an API key? Pass api_key= and the wallet is only used to pay.
With LangChain
from langchain_openai import ChatOpenAI
from neura_agent import NeuraAgent
neura = NeuraAgent(wallet_key=os.environ["AGENT_WALLET_KEY"], auto_fund=True)
llm = ChatOpenAI(
model="openai/gpt-oss-120b",
base_url=neura.base_url + "/v1",
api_key="wallet",
http_client=neura.http_client(),
)
print(llm.invoke("Who pays for this call?").content)
With CrewAI
CrewAI routes through LiteLLM, which does not take a custom http client, so pre-fund before the crew runs and give it the provisioned key:
from crewai import LLM
from neura_agent import NeuraAgent
neura = NeuraAgent(wallet_key=os.environ["AGENT_WALLET_KEY"], auto_fund=True)
neura.login_with_wallet()
if neura.credit_balance() < 2:
neura.fund(neura.discovery(), credits=2) # 2 USDC -> 2 credits
llm = LLM(model="openai/openai/gpt-oss-120b", base_url=neura.base_url + "/v1", api_key=neura.api_key)
See examples/ for runnable versions of all three.
What the platform sends, and what the client does with it
A 402 carries an x402 v1 envelope. Production today:
{
"code": "PAYMENT_REQUIRED",
"x402Version": 1,
"accepts": [{
"scheme": "exact", "network": "base",
"maxAmountRequired": "1000000",
"payTo": "0x404f4E91Fc8Bf0c5fcfC71b4C06E2c0faACdb2c5",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": { "settlement": "transfer", "assetSymbol": "USDC", "decimals": 6,
"creditEndpoint": "/api/depin/credits/topup-usdc" }
}],
"authenticate": { "scheme": "EIP-4361", "nonce": "/api/auth/wallet/nonce", "verify": "/api/auth/wallet" }
}
choose_offer(body) picks the rail: the USDC exact offer whenever present;
a neura-burn offer only when advertised with a live rate. If the platform
offers nothing the client can settle, it raises instead of guessing.
Safety model
- Nothing moves on-chain unless you pass
wallet_keyandauto_fund=True(or callfund()yourself). - A returning wallet pays nothing to resume: after the SIWE login the client retries with the tenant's key first, and funds only if the platform still answers 402 for that tenant. Restarting an agent never buys credits it has.
max_usdc_per_fund(default 5) caps any single payment;max_neura_per_burn(default 100) caps any burn.pin_pay_torefuses to send USDC to any receiver other than the one you pin.- On 402 without auto-funding,
PaymentRequiredErrorcarriesremediation,x402and the fullbodyso your own logic can decide. - Use a dedicated hot wallet with a small balance — never a treasury key.
Allowances: the owner's leash, honoured by the client
The platform's owner-set allowances answer with 403/429 and a code. The
client reads them before it ever thinks about paying:
AGENT_PAUSED(the owner's kill switch) raisesAgentPausedError. The client never funds, never retries: only the owner can resume the key.ALLOWANCE_DAILY,ALLOWANCE_MONTHLY,OUTSIDE_ALLOWED_HOURS,SELF_LIMIT_EXCEEDEDare retryable and come withRetry-After. By default the client raisesAllowanceErrorwithretry_after_secondsso your loop can decide. Setmax_retry_after_secondsand, when the wait fits, the client sleeps exactly that long and retries once.MODEL_NOT_ALLOWED,ALLOWANCE_PER_CALLare not retryable and raiseAllowanceErrorwithretryable=Falseeven when waiting is allowed.- Any other 403/429 passes through untouched.
The agent's own key can only tighten its allowance (PUT /api/agent/allowance).
A wallet tenant has no console, so its owner acts by signature:
agent.owner_allowance(api_key_id, allowance={...}), action="kill" or
action="resume" signs a fresh SIWE message with wallet_key and posts it to
/api/agent/allowance/owner. Run that where the wallet lives, not inside the
agent: whoever can sign can loosen the leash.
API
| Member | Purpose |
|---|---|
NeuraAgent(...) |
api_key, base_url, wallet_key, auto_fund, credits_per_fund, max_usdc_per_fund, max_neura_per_burn, confirmations, rpc_url, pin_pay_to, max_retry_after_seconds |
agent.owner_allowance(api_key_id, allowance=None, action=None, reason=None) |
Owner-by-signature: set any allowance field, or action="kill" / "resume" |
AgentPausedError / AllowanceError |
Raised on AGENT_PAUSED / on an allowance refusal (code, retryable, retry_after_seconds, body) |
agent.http_client() |
An httpx.Client whose send settles 402s — pass to OpenAI / LangChain |
agent.chat(model, messages, **params) |
Plain chat completion with the same 402 handling |
agent.login_with_wallet() |
SIWE login → {tenantId, address, apiKey} |
agent.fund(body, credits=None) |
Settle a 402 body (or a single offer) on the rail it advertises |
agent.fund_usdc(offer, credits) / agent.fund_burn(remediation) |
The rails individually |
agent.credit_balance() |
Current credits (1 = $1) |
agent.discovery() |
/.well-known/neura.json |
choose_offer(body) |
Which rail a 402 lets the client settle |
PaymentRequiredError |
Raised on unhandled 402 — carries remediation, x402, body |
Develop / publish
cd packages/neura-agent-py
pip install -e ".[test]"
pytest
python -m build && twine upload dist/*
Metadata
Release files for neura-agent 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| neura_agent-0.2.1.tar.gz | 16.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| neura_agent-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.9 kB
Release files / neura_agent-0.2.1.tar.gz
| Download URL | neura_agent-0.2.1.tar.gz |
|---|---|
| Size | 16.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
de320dedd51294bb3a5a8947fa6d208eb579779a456b3aecd6bbb1fd7216b900
|
|
BLAKE2b-256 checksum How to use checksums |
8a94b17af8a6baf2007a9f8f2b48de780e727b98091af9d6ee443231b3702685
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.11
|
Release files / neura_agent-0.2.1-py3-none-any.whl
| Download URL | neura_agent-0.2.1-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1a5f4eadf7a576f07fb02efe61cd998c56a19e33b2ebae521b173330e6cafd3e
|
|
BLAKE2b-256 checksum How to use checksums |
f0fbb93cc08569c8d901b3d6b1e5a2aa19c9e35e7fcf55d9b4303e6b191f430e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.11
|