Hermes Bort: BORT Agent Integration for Hermes Agent
Connects Hermes Agent to BORT (BAP-578) agent NFTs on BSC mainnet.
- Author
- BORT-AGENTS
- Stars
- 3
- Language
- Python
- License
- MIT
- Upstream updated
- 2026-05-18

Hermes BORT Plugin Reference
This plugin enables Hermes Agent to interact with BORT (BAP-578) agent NFTs on BSC mainnet. It supports reading on-chain state, executing operator-signed writes, managing portable IPFS-anchored memory, and committing verifiable learning records for self-evolution.
When to Use
Use this plugin when a Hermes process needs to:
- Read the on-chain state of a BORT agent NFT.
- Execute on-chain actions for a BORT agent via operator-signed writes.
- Manage portable session memory anchored to IPFS and KnowledgeRegistryV2.
- Integrate with the hermes-agent-self-evolution optimizer to commit verifiable on-chain learning records.
Prerequisites
- Hermes Agent installed.
- Python environment with pip.
- For reads only: no setup beyond installation.
- For writes: an operator key generated and funded with approximately 0.01 BNB, a policy file created, and the agent owner must grant operator permission via two-step calldata.
- For IPFS anchoring: Pinata API key and secret set.
- For evolve: the hermes-agent-self-evolution repository available.
- BSC mainnet access (public RPC or custom).
- BORT runtime API accessible (default:
https://bap578-nfa-platform.onrender.com).
Installation
- Run
pip install hermes-bort. - Or run
hermes plugins install BORT-AGENTS/hermes-bort. - Enable the plugin in
~/.hermes/config.yamlunderplugins: enabled: [hermes-bort]. - Alternatively, clone the repository and run
pip install -e .[dev]. - Or drop the
hermes_bort/package into~/.hermes/plugins/directly.
Configuration
Environment Variables
The plugin reads the following environment variables. Each variable has a specific purpose and default value.
BORT_API_URL: Runtime API base URL. Optional. Default:https://bap578-nfa-platform.onrender.com.BSC_RPC_URL: BSC RPC endpoint. Optional. Default:https://bsc-dataseed.binance.org.BORT_DAPP_URL: Dapp URL for deep links. Optional. Default:https://www.bortagent.xyz.BORT_MEMORY_DIR: Directory for local memory files. Optional. Default:~/.hermes/bort-memory.BORT_OPERATOR_PRIVATE_KEY: Operator private key for signing writes. Required for writes. Default: unset (writes disabled).BORT_ALLOW_BROADCAST: Flag to enable real broadcasting of writes instead of simulation only. Optional. Default: unset (simulate only).BORT_POLICY_PATH: Path to policy file. Optional. Default:~/.hermes/bort-policy.yaml.PINATA_API_KEY: Pinata API key for IPFS pinning. Required for anchor tools. Default: unset.PINATA_API_SECRET: Pinata API secret for IPFS pinning. Required for anchor tools. Default: unset.BORT_SELF_EVOLUTION_REPO: Path to hermes-agent-self-evolution repository. Optional for evolve. Default:~/.hermes/hermes-agent-self-evolutionor sibling directory.BORT_TEST_TOKEN_ID: Token ID used for testing. Optional. Used in pytest.
Command-Line Flags for Evolve
--iterations: GEPA iterations for evolve. Default: 10.--optimizer-model: LLM for GEPA reflections in litellm format (e.g.,anthropic/claude-sonnet-4-6). Optional. Default: optimizer's own default.--eval-model: LLM for evaluations in litellm format. Optional.--repo: Path to hermes-agent-self-evolution repository. Optional.--commit-only: Skip optimizer; commit the latest existing run directory. Optional.--only: Which on-chain steps to run:both,evolution, orlearning. Default:both.--min-improvement: Only commit ifmetrics.improvement >= F. Optional.
Quickstart
Read-Only Quickstart
No setup beyond installation is required for reads. Reads hit the public BORT runtime API and BSC public RPC.
Use Python:
from hermes_bort.tools.read_agent import handle as read_agent
import asyncio, json
raw = asyncio.run(read_agent({'token_id': 11100}))
print(json.dumps(json.loads(raw), indent=2)[:800])
Inside Hermes, use the tool bort_read_agent(token_id=11100).
Configure for Writes
- Generate an operator key:
hermes bort init-operator. This prints the address and private key. SetBORT_OPERATOR_PRIVATE_KEYin the environment. Fund the address with approximately 0.01 BNB for gas. - Write a default policy:
hermes bort init-policy. This writes~/.hermes/bort-policy.yaml. Each action has a disposition (auto,confirm, orblock) and an optionalper_action_max_bnbcap. - Have the agent owner grant operator permission. Use Python:
from hermes_bort.tools.grant_permission import handle as grant
raw = await grant({'token_id': 11100, 'operator': '0xYourOperatorAddress'})
This returns two-step calldata (createVault then grantPermission) for the owner to sign.
4. Run writes. By default, writes simulate only. Set BORT_ALLOW_BROADCAST=1 to enable real broadcasting.
Doctor (Setup Verification)
Run hermes bort doctor. This checks:
- RPC reachable.
- Operator key valid and funded.
- Policy file present and parseable.
- Pinata credentials set if anchoring memory.
- hermes-agent-self-evolution repository present if using evolve.
Tools
Read Tools
bort_read_agent: Reads full agent state, IPFS identity, and knowledge registries.bort_health_check: Checks connectivity.bort_list_actions: Lists available actions for an agent.bort_marketplace_browse: Browses marketplace listings. Example:bort_marketplace_browse(sort='price_asc', limit=10)prints listings with token_id, price_per_token, and lister.bort_marketplace_agent: Gets marketplace details for a specific agent.bort_list_agent_uri: Generates owner-signed deep links into the BORT dapp for marketplace flows. Example:bort_list_agent_uri(token_id=11100, intent='list')returns a URL likehttps://www.bortagent.xyz/#/my-listings.
Write Tools
bort_grant_permission_uri: Generates a URI for the owner to grant operator permission.bort_commit_learning: Commits a learning record.bort_invoke: Executes on-chain actions via VaultPermissionManagerV2 with local policy gating. Example:bort_invoke(token_id=11100, action='buy_token', args={'token_address': '0x...', 'amount_bnb_wei': 100000000000000000})returns status (broadcast,simulated_only, orblocked) and tx_hash.bort_anchor_memory: Anchors local session memory to IPFS and KnowledgeRegistryV2.bort_commit_evolution: Commits an evolved skill and learning record on-chain.
Write Preflight Checks
Before any write is broadcast, the plugin performs these checks in order:
- CircuitBreaker global pause.
- Contract pause.
- VPMv2.canForward returns true.
- Policy disposition (auto, confirm, block).
- If disposition is confirm, Hermes approval prompt.
If any check fails, the write is blocked. Without BORT_ALLOW_BROADCAST, writes return simulated_only.
Memory Portability
The plugin provides portable session memory. During a chat, session data is written to ~/.hermes/bort-memory/<tokenId>.jsonl. At session end or when bort_anchor_memory is called, the buffer is pinned to IPFS via Pinata and committed to KnowledgeRegistryV2 as a MEMORY source through the operator's WRITE grant. At the next session start, the provider pulls active MEMORY sources from KnowledgeRegistry.getActiveKnowledgeSources(tokenId) and exposes them for prefetch. The BortMemoryProvider keys session memory by tokenId, so memory travels with the NFT across different Hermes instances.
To anchor session memory to IPFS:
- Ensure the agent owner has granted the operator WRITE permission.
- Run
hermes bort anchor-memory --token-id <N>. - This turns the local JSONL buffer into an on-chain MEMORY knowledge source for the next session to prefetch.
Evolve (Self-Evolution)
Run hermes bort evolve <skill> --token-id <N>. This runs the optimizer as a subprocess. Only if metrics.json shows real improvement, it chains two on-chain writes linked by one content hash:
commit_evolution: Pins the evolved skill to IPFS and writes it as an INSTRUCTION knowledge source on KnowledgeRegistryV2.commit_learning: Emits a LearningRecorded event on the agent's logic contract.
The self-evolution repository is located via --repo, $BORT_SELF_EVOLUTION_REPO, ~/.hermes/hermes-agent-self-evolution, or a sibling directory.
Without BORT_ALLOW_BROADCAST, the entire loop is a dry run: the skill is pinned to IPFS, but both chain writes simulate only.
If commit_evolution succeeds but commit_learning fails, retry with: hermes bort evolve <skill> --token-id N --commit-only --only learning.
Each run is a distinct on-chain event; the knowledge registry does not deduplicate.
The LLM provider for evolve can be any litellm-supported provider. The API key is read from the environment (e.g., ANTHROPIC_API_KEY, DEEPSEEK_API_KEY).
Sanitization
The plugin treats free-form text fields (identity name/description, knowledge source descriptions, prefetched memory) as untrusted. It wraps them in a <external-data> envelope with a preamble, caps them at 2KB with a truncation marker, and strips C0 controls, ANSI escapes, zero-width characters, and bidi-override Unicode characters. Numeric IDs, addresses, on-chain enums, and structural keys are not wrapped. This sanitization raises the bar from trivial injection but is not a complete defense; the operator-key boundary is the primary security measure.
Failure Modes
- Operator key not set or invalid: writes disabled or fail.
- Operator key not funded: gas insufficient for writes.
- Policy file missing or malformed: writes blocked.
BORT_ALLOW_BROADCASTunset: writes simulate only, no real broadcast.- Pinata credentials missing: anchor tools return a clear error.
- Self-evolution repository not found: evolve command fails.
- Agent owner has not granted operator permission: writes fail.
- CircuitBreaker paused (global or per-contract): write preflight fails.
- VPMv2.canForward returns false: writes blocked.
- Policy disposition blocks action: writes blocked.
- Hermes approval prompt declined (for confirm dispositions): writes cancelled.
- IPFS pinning fails:
commit_evolutionoranchor_memoryfails. - On-chain write fails (e.g., revert, gas): transaction not broadcast or fails.
- Memory file not found:
anchor_memoryfails. - Network unreachable: reads and writes fail.
Constraints and Caveats
- The operator key is never written to disk by the plugin; it is printed once to stdout for the user to set in the environment.
- The operator can only do what the owner has granted in VaultPermissionManagerV2 and what the policy file allows.
- A leaked operator key can be revoked by the owner with one
revokePermissiontransaction. The operator cannot mint, transfer, or list the NFT. commit_evolutionneeds Pinata credentials;commit_learningdoes not (it only emits a content hash).- The plugin includes 99 tests, most integration-style hitting BSC mainnet RPC and the BORT runtime API. Network tests are skipped when the relevant environment variable is unset.
Examples
Read an agent: use bort_read_agent with token_id=11100 to print the owner and logic name/snapshot.
Browse marketplace: use bort_marketplace_browse with sort='price_asc', limit=10 to print listings with token_id, price_per_token, and lister.
Drive an action through operator: after granting permission, use bort_invoke with token_id=11100, action='buy_token', and args including token_address and amount_bnb_wei. The response shows status (broadcast, simulated_only, or blocked) and tx_hash.
Anchor session memory to IPFS: run hermes bort anchor-memory --token-id 11100 after the owner grants WRITE permission.
Generate marketplace deep link: use bort_list_agent_uri with token_id=11100 and intent='list' to get a URL like https://www.bortagent.xyz/#/my-listings.
Detailed Tool Reference
bort_read_agent
This tool fetches the complete on-chain state of a BORT agent NFT. It returns the owner address, logic contract name and snapshot, IPFS identity, and any knowledge registries associated with the token. The tool requires a single parameter token_id as an integer. The response is a JSON string that can be parsed and inspected. The tool connects to the BORT runtime API and BSC RPC to gather this data. If the token ID does not exist on-chain, the tool returns an error indicating the token was not found.
bort_health_check
This tool verifies connectivity to the BORT runtime API and BSC RPC. It returns a status message indicating whether both endpoints are reachable. Use this tool before any other operations to confirm network access. The tool takes no parameters.
bort_list_actions
This tool lists all available on-chain actions for a specific BORT agent. It requires a token_id parameter. The response includes action names and their expected arguments. This is useful for determining what actions can be passed to bort_invoke. The tool queries the agent's logic contract through the runtime API.
bort_marketplace_browse
This tool browses the BORT marketplace for agent listings. It accepts optional parameters sort (default price_asc) and limit (default 10). The response prints a table of listings with columns for token_id, price_per_token, and lister address. The tool connects to the BORT marketplace contract on BSC. If no listings are found, the tool returns an empty list.
bort_marketplace_agent
This tool retrieves marketplace details for a specific agent. It requires a token_id parameter. The response includes the listing price, lister address, and any other marketplace metadata. The tool queries the marketplace contract directly.
bort_list_agent_uri
This tool generates a deep link URL for the BORT dapp. It requires token_id and intent parameters. The intent parameter can be list or unlist. The returned URL can be opened in a browser to perform the corresponding marketplace action. The tool constructs the URL using the BORT_DAPP_URL environment variable.
bort_grant_permission_uri
This tool generates a URI that the agent owner can use to grant operator permission. It requires token_id and operator address parameters. The returned URI contains calldata for the two-step process (createVault then grantPermission). The owner must sign and submit this calldata to the blockchain. The tool does not submit the transaction itself.
bort_commit_learning
This tool commits a learning record on-chain for a BORT agent. It requires token_id and a content_hash parameter (a string representing the IPFS content hash of the learning data). The tool emits a LearningRecorded event on the agent's logic contract. This tool does not require Pinata credentials because it only emits a hash, not pinning data. The operator must have WRITE permission from the agent owner.
bort_invoke
This tool executes an on-chain action via the VaultPermissionManagerV2 contract. It requires token_id, action (a string matching an action from bort_list_actions), and args (a dictionary of action-specific parameters). The tool performs write preflight checks before execution. The response includes status which is one of broadcast, simulated_only, or blocked. If broadcast, the response also includes tx_hash. The tool respects the BORT_ALLOW_BROADCAST environment variable.
bort_anchor_memory
This tool anchors local session memory to IPFS and KnowledgeRegistryV2. It requires token_id as a parameter. The tool reads the local JSONL buffer from BORT_MEMORY_DIR, pins it to IPFS via Pinata, and commits it as a MEMORY knowledge source on-chain. The tool requires Pinata credentials to be set. If the memory file does not exist, the tool returns an error.
bort_commit_evolution
This tool commits an evolved skill and learning record on-chain. It requires token_id and a skill_content_hash parameter. The tool pins the evolved skill to IPFS and writes it as an INSTRUCTION knowledge source on KnowledgeRegistryV2. It also emits a LearningRecorded event. This tool requires Pinata credentials for the IPFS pinning step. The operator must have WRITE permission.
Policy File Format
The policy file is a YAML file located at BORT_POLICY_PATH (default ~/.hermes/bort-policy.yaml). Each action has a disposition and an optional per_action_max_bnb cap. The disposition can be auto (allow without prompt), confirm (prompt user for approval), or block (deny the action). The per_action_max_bnb cap limits the maximum BNB value for that action in wei. Example policy:
actions:
buy_token:
disposition: auto
per_action_max_bnb: 100000000000000000
sell_token:
disposition: confirm
transfer:
disposition: block
If an action is not listed in the policy, the default disposition is block.
Operator Key Management
The operator key is generated with hermes bort init-operator. The plugin prints the private key and address to stdout once. The user must set BORT_OPERATOR_PRIVATE_KEY in the environment. The plugin never writes the private key to disk. The operator address must be funded with approximately 0.01 BNB for gas. The operator can only perform actions that the agent owner has granted in VaultPermissionManagerV2 and that the policy file allows. The owner can revoke operator permission at any time with a single revokePermission transaction. The operator cannot mint, transfer, or list the NFT.
Granting Operator Permission
The agent owner must grant operator permission through a two-step process. First, a vault is created for the agent. Second, the operator is granted permission on that vault. The bort_grant_permission_uri tool generates the calldata for both steps. The owner must sign and submit this calldata to the blockchain. The plugin does not submit the transaction. The permission grant is specific to a token ID and operator address. The owner can specify which actions the operator is allowed to perform.
Testing
The plugin includes 99 tests, most integration-style hitting BSC mainnet RPC and the BORT runtime API. Network tests are skipped when the relevant environment variable is unset. The BORT_TEST_TOKEN_ID environment variable specifies which token ID to use for testing. Tests cover read tools, write tools, memory portability, and evolve functionality. To run tests, use pytest from the plugin directory.
Troubleshooting
If writes fail, check the following in order:
- Run
hermes bort doctorto verify setup. - Confirm
BORT_OPERATOR_PRIVATE_KEYis set correctly. - Verify the operator address has sufficient BNB for gas.
- Check the policy file exists and is valid YAML.
- Confirm the agent owner has granted operator permission.
- Set
BORT_ALLOW_BROADCAST=1if you want real broadcasts. - Check network connectivity to BSC RPC and BORT API.
If memory anchoring fails, verify PINATA_API_KEY and PINATA_API_SECRET are set. If evolve fails, confirm the hermes-agent-self-evolution repository is present and the LLM API keys are set in the environment.
Sources & References
This page was researched from 2 independent sources, combined and verified for completeness.
- 1.BORT-AGENTS/hermes-bortBlog · primary source
- 2.BORT-AGENTS/hermes-bort READMEOfficial documentation
The #1 AI Newsletter
The most important ai updates, guides, and fixes — one weekly email.
No spam, unsubscribe anytime. Privacy policy