API Module
The API module provides a high-level interface for building Neuro API game clients. This module builds upon the foundational client and command modules to offer a complete, abstract base class for game integration with the Neuro system.
Overview
The API module contains the main AbstractNeuroAPI class that game developers should inherit from to create their Neuro-integrated games. It handles action registration, command processing, and provides hooks for game-specific implementations. This module abstracts away much of the low-level command formatting and message handling.
Classes
NeuroAction
- class neuro_api.api.NeuroAction(id_: str, name: str, data: str | None)
Representation of a Neuro Action with its associated details.
A NamedTuple that encapsulates the essential information for an action in the Neuro game interaction system.
- id_
Unique identifier for the action. The trailing underscore is used to avoid conflicts with Python’s built-in id keyword.
- Type:
- data
Optional additional data associated with the action. Can be None if no additional information is required.
- Type:
str | None
A named tuple representing an action request from Neuro with all necessary details.
Attributes:
id_ (str): Unique identifier for the action (underscore avoids Python’s
idkeyword)name (str): Name of the action to be performed
data (str | None): Optional JSON-stringified data for the action
Example:
action = NeuroAction( id_="action_123", name="move_player", data='{"direction": "north", "steps": 3}' )
AbstractNeuroAPI
- class neuro_api.api.AbstractNeuroAPI(game_title: str)
Abstract base class for the Neuro Game Interaction API.
Provides a foundational interface for managing game actions and interactions with the Neuro system. This class is designed to be subclassed by specific game implementations.
Note
This is an abstract base class that requires implementation of specific game interaction methods in subclasses.
High-level abstract base class for Neuro API game clients.
This class provides a complete framework for integrating games with the Neuro system. It handles:
Action registration and management
Command processing and routing
Context communication with Neuro
Shutdown handling for automated games
Internal state tracking
Attributes:
game_title (str): The name of the integrated game
- __init__(game_title: str) None
Initialize the Neuro API for a specific game.
- Parameters:
game_title (str) – The name of the game to be integrated with the Neuro system.
Note
Initializes the internal action registry to track currently registered actions.
- get_registered() tuple[str, ...]
Return the names of all currently registered actions.
- Returns:
A tuple containing the names of all actions currently registered in the Neuro API.
- Return type:
Note
This method provides a snapshot of registered actions at the time of calling.
- async send_startup_command() None
Send startup command to initialize the game with Neuro.
This method sends the initial message to the Neuro system when a game starts. It serves two critical purposes: - Inform Neuro that the game is now running - Clear and reset any previously registered actions
Note
This should be the very first message sent after game initialization.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the startup command.
Warning
Sends a command that clears all previously registered actions for this game, performing a complete action registry reset.
- async send_context(message: str, silent: bool = True) None
Send a contextual message to Neuro about the game state.
Allows communication of game events or state information to Neuro without necessarily requiring an immediate response.
- Parameters:
message (str) – A plaintext description of what is happening in the game. This information will be directly received by Neuro.
silent (bool, optional) –
Controls Neuro’s response behaviour: - If True (default): Message is added to context silently
without prompting a response.
If False: Neuro _might_ respond directly, unless she is busy talking to someone else or to chat.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the context command.
Note
This method provides a flexible way to keep Neuro informed about game events without disrupting ongoing interactions.
- async register_actions(actions: list[Action]) None
Register a list of actions with Neuro.
Validates and registers multiple actions for Neuro to use during game interaction. This method performs two key operations: - Validates each action’s name and schema - Sends the actions to Neuro for registration
- Parameters:
actions (list[command.Action]) – A list of actions to be registered. If an action is already registered, it will be ignored.
- Raises:
ValueError – If any action: - Contains invalid characters in its name - Has an invalid schema key
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action registration.
Note
Each action is validated before registration
Previously registered actions with the same name will not be overwritten
The method maintains an internal registry of registered actions
- async unregister_actions(action_names: Sequence[str]) None
Unregister specified Neuro actions.
Removes actions from both the internal registry and Neuro’s action set, preventing these actions from being used in future interactions.
- Parameters:
action_names (Sequence[str]) – The names of the actions to unregister. Attempting to unregister an action that isn’t registered will not cause any errors.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action unregistration.
Note
No error is raised for non-existent actions
- async send_force_action(state: str, query: str, action_names: Sequence[str], ephemeral_context: bool = False, priority: ForcePriority = ForcePriority.LOW) None
Force Neuro to execute an action with specific context.
Sends a command to Neuro that compels her to choose and execute one of the specified actions, providing detailed game state and action instructions.
- Parameters:
state (str) – An arbitrary string describing the current game state. Can be plaintext, JSON, Markdown, or any other format. This information will be directly received by Neuro.
query (str) – A plaintext message instructing Neuro on her current task (e.g., “It is now your turn. Please perform an action. If you want to use any items, you should use them before picking up the shotgun.”). This information will be directly received by Neuro.
action_names (Sequence[str]) – Names of actions Neuro can choose from during this force action.
ephemeral_context (bool, optional) –
Controls context persistence: - If False (default): The state and query context will
be remembered after actions force completion.
If True: Neuro will only remember the context during the actions force.
priority (command.ForcePriority) – Determines how urgently Neuro should respond to the action force when she is speaking. If Neuro is not speaking, this setting has no effect. The default is command.ForcePriority.LOW, which will cause Neuro to wait until she finishes speaking before responding. command.ForcePriority.MEDIUM causes her to finish her current utterance sooner. command.ForcePriority.HIGH prompts her to process the action force immediately, shortening her utterance and then responding. command.ForcePriority.CRITICAL will interrupt her speech and make her respond at once. Use command.ForcePriority.CRITICAL with caution, as it may lead to abrupt and potentially jarring interruptions.
- Raises:
ValueError – If any specified action name is not currently registered.
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action force command.
Warning
Neuro can only handle one action force at a time.
Sending an action force while another is in progress will cause problems.
- async send_action_result(id_: str, success: bool, message: str | None = None) None
Report the result of a Neuro-initiated action.
Communicates the outcome of an action to Neuro, allowing her to proceed with her decision-making process. This method is critical for maintaining the flow of game interactions.
- Parameters:
id (str) – The unique identifier of the action being reported. This ID is directly obtained from the original action message.
success (bool) –
Indicates the action’s outcome: - If True: Action was successfully executed. - If False: Action failed. Note: If this action is part
of an actions force, Neuro will immediately retry the entire actions force.
message (str, optional) –
A descriptive message about the action’s execution: - For unsuccessful actions: Should be an error message. - For successful actions: Can be empty or provide a _small_
context about the action (e.g., “Remember to not share this with anyone.”).
This information will be directly received by Neuro.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action result.
Warning
Until an action result is sent, Neuro will be waiting and unable to proceed.
Send this method call as soon as possible after action validation, preferably before in-game execution.
Note
To prevent automatic retrying of a failed action: - Set success to True - Provide an error message in the message field
- async send_shutdown_ready() None
Send shutdown ready response.
This is part of the game automation API, which will only be used for games that Neuro can launch by herself. As such, most games will not need to implement this.
This should be sent as a response to a graceful or an imminent shutdown request, after progress has been saved. After this is sent, Neuro will close the game herself by terminating the process, so to reiterate you must definitely ensure that progress has already been saved.
- Raises:
UnicodeDecodeError – If data is unable to be decoded (though this is unlikely to happen).
orjson.JSONEncodeError – If unable to encode JSON data.
- abstractmethod async handle_action(action: NeuroAction) None
Handle an Action request from Neuro.
- Parameters:
action (NeuroAction) – Parsed Neuro action request data.
Warning
Should call
send_action_resultwith this action’s id as soon as scheduling action processing is complete, or else Neuro will be stuck frozen, waiting.
- async handle_graceful_shutdown_request(wants_shutdown: bool) None
Handle a graceful shutdown request from Neuro.
This is part of the game automation API, which will only be used for games that Neuro can launch by herself. As such, most games will not need to implement this.
This message will be sent when Neuro decides to stop playing a game, or upon manual intervention from the dashboard. You should create or identify graceful shutdown points where the game can be closed gracefully after saving progress. You should store the latest received wants_shutdown value, and if it is true when a graceful shutdown point is reached, you should save the game and quit to main menu, then send back a shutdown ready message.
- Parameters:
wants_shutdown (bool) – Whether the game should shutdown at the next graceful shutdown point. - If True: Shutdown is requested - If False: Cancel the prior shutdown request
Warning
Please don’t actually close the game, just quit to main menu. Neuro will close the game herself.
Note
Base implementation sends that shutdown is ready.
- async handle_immediate_shutdown() None
Handle immediate shutdown alert from Neuro.
This is part of the game automation API, which will only be used for games that Neuro can launch by herself. As such, most games will not need to implement this.
This message will be sent when the game needs to be shutdown immediately. You have only a handful of seconds to save as much progress as possible. After you have saved, you can send back a shutdown ready message.
Warning
Please don’t actually close the game, just save the current progress that can be saved. Neuro will close the game herself.
Note
Base implementation sends that shutdown is ready.
- async read_message() None
Read message from Neuro websocket.
You should call this function in a loop as long as the websocket is still connected.
Automatically handles actions/reregister_all commands.
Calls
handle_graceful_shutdown_requestandhandle_immediate_shutdownfor graceful and immediate shutdown requests respectively.Calls
handle_actionfor action commands.Calls
handle_unknown_commandfor any other command.- Raises:
ValueError – If extra keys in action command data or missing keys in action command data.
TypeError – If action command key type mismatch
Note
Does not catch any exceptions
read_raw_server_messageraises.
Initialization
- AbstractNeuroAPI.__init__(game_title: str) None
Initialize the Neuro API for a specific game.
- Parameters:
game_title (str) – The name of the game to be integrated with the Neuro system.
Note
Initializes the internal action registry to track currently registered actions.
Initialize the Neuro API client for a specific game.
The game title should be the display name of your game, including spaces and symbols (e.g., “Buckshot Roulette”, “Among Us”).
Core Methods
These methods provide the primary functionality for game integration:
- async AbstractNeuroAPI.send_startup_command() None
Send startup command to initialize the game with Neuro.
This method sends the initial message to the Neuro system when a game starts. It serves two critical purposes: - Inform Neuro that the game is now running - Clear and reset any previously registered actions
Note
This should be the very first message sent after game initialization.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the startup command.
Warning
Sends a command that clears all previously registered actions for this game, performing a complete action registry reset.
Critical: This must be the first command sent when your game starts.
async def game_startup(): api = MyGameAPI("My Game") await api.send_startup_command() # Clear previous state # Now register actions...
- async AbstractNeuroAPI.send_context(message: str, silent: bool = True) None
Send a contextual message to Neuro about the game state.
Allows communication of game events or state information to Neuro without necessarily requiring an immediate response.
- Parameters:
message (str) – A plaintext description of what is happening in the game. This information will be directly received by Neuro.
silent (bool, optional) –
Controls Neuro’s response behaviour: - If True (default): Message is added to context silently
without prompting a response.
If False: Neuro _might_ respond directly, unless she is busy talking to someone else or to chat.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the context command.
Note
This method provides a flexible way to keep Neuro informed about game events without disrupting ongoing interactions.
Communicate game events and state to Neuro.
# Silent context (no response expected) await api.send_context("Player entered the forest area") # Interactive context (may prompt response) await api.send_context("Player seems confused and stuck", silent=False)
- async AbstractNeuroAPI.register_actions(actions: list[Action]) None
Register a list of actions with Neuro.
Validates and registers multiple actions for Neuro to use during game interaction. This method performs two key operations: - Validates each action’s name and schema - Sends the actions to Neuro for registration
- Parameters:
actions (list[command.Action]) – A list of actions to be registered. If an action is already registered, it will be ignored.
- Raises:
ValueError – If any action: - Contains invalid characters in its name - Has an invalid schema key
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action registration.
Note
Each action is validated before registration
Previously registered actions with the same name will not be overwritten
The method maintains an internal registry of registered actions
Register actions that Neuro can execute in your game.
from neuro_api.command import Action actions = [ Action( name="move_player", description="Move the player character", schema={ "type": "object", "properties": { "direction": {"type": "string"}, "distance": {"type": "integer", "minimum": 1} }, "required": ["direction"] } ), Action("jump", "Make the player jump"), Action("attack", "Attack nearby enemies") ] await api.register_actions(actions)
- async AbstractNeuroAPI.unregister_actions(action_names: Sequence[str]) None
Unregister specified Neuro actions.
Removes actions from both the internal registry and Neuro’s action set, preventing these actions from being used in future interactions.
- Parameters:
action_names (Sequence[str]) – The names of the actions to unregister. Attempting to unregister an action that isn’t registered will not cause any errors.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action unregistration.
Note
No error is raised for non-existent actions
Remove actions that are no longer available.
# Remove specific actions await api.unregister_actions(["attack", "use_magic"])
- async AbstractNeuroAPI.send_force_action(state: str, query: str, action_names: Sequence[str], ephemeral_context: bool = False, priority: ForcePriority = ForcePriority.LOW) None
Force Neuro to execute an action with specific context.
Sends a command to Neuro that compels her to choose and execute one of the specified actions, providing detailed game state and action instructions.
- Parameters:
state (str) – An arbitrary string describing the current game state. Can be plaintext, JSON, Markdown, or any other format. This information will be directly received by Neuro.
query (str) – A plaintext message instructing Neuro on her current task (e.g., “It is now your turn. Please perform an action. If you want to use any items, you should use them before picking up the shotgun.”). This information will be directly received by Neuro.
action_names (Sequence[str]) – Names of actions Neuro can choose from during this force action.
ephemeral_context (bool, optional) –
Controls context persistence: - If False (default): The state and query context will
be remembered after actions force completion.
If True: Neuro will only remember the context during the actions force.
priority (command.ForcePriority) – Determines how urgently Neuro should respond to the action force when she is speaking. If Neuro is not speaking, this setting has no effect. The default is command.ForcePriority.LOW, which will cause Neuro to wait until she finishes speaking before responding. command.ForcePriority.MEDIUM causes her to finish her current utterance sooner. command.ForcePriority.HIGH prompts her to process the action force immediately, shortening her utterance and then responding. command.ForcePriority.CRITICAL will interrupt her speech and make her respond at once. Use command.ForcePriority.CRITICAL with caution, as it may lead to abrupt and potentially jarring interruptions.
- Raises:
ValueError – If any specified action name is not currently registered.
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action force command.
Warning
Neuro can only handle one action force at a time.
Sending an action force while another is in progress will cause problems.
Force Neuro to choose from specific actions immediately.
Warning
Only one action force can be active at a time. Multiple concurrent forces will cause problems.
await api.send_force_action( state="Player HP: 25/100, Enemy HP: 50/100, In combat", query="Choose your action for this turn in combat", action_names=["attack", "defend", "use_potion", "flee"], ephemeral_context=True # Don't remember this context after action )
- async AbstractNeuroAPI.send_action_result(id_: str, success: bool, message: str | None = None) None
Report the result of a Neuro-initiated action.
Communicates the outcome of an action to Neuro, allowing her to proceed with her decision-making process. This method is critical for maintaining the flow of game interactions.
- Parameters:
id (str) – The unique identifier of the action being reported. This ID is directly obtained from the original action message.
success (bool) –
Indicates the action’s outcome: - If True: Action was successfully executed. - If False: Action failed. Note: If this action is part
of an actions force, Neuro will immediately retry the entire actions force.
message (str, optional) –
A descriptive message about the action’s execution: - For unsuccessful actions: Should be an error message. - For successful actions: Can be empty or provide a _small_
context about the action (e.g., “Remember to not share this with anyone.”).
This information will be directly received by Neuro.
- Raises:
UnicodeDecodeError – If the command data cannot be decoded (highly unlikely).
orjson.JSONEncodeError – If unable to encode the JSON data for the action result.
Warning
Until an action result is sent, Neuro will be waiting and unable to proceed.
Send this method call as soon as possible after action validation, preferably before in-game execution.
Note
To prevent automatic retrying of a failed action: - Set success to True - Provide an error message in the message field
Report the outcome of an action execution.
Important
Send this immediately after validating the action, not after executing it in-game.
# Successful action await api.send_action_result( action.id_, success=True, message="Successfully moved north" ) # Failed action await api.send_action_result( action.id_, success=False, message="Cannot move - path blocked by wall" )
Utility Methods
- AbstractNeuroAPI.get_registered() tuple[str, ...]
Return the names of all currently registered actions.
- Returns:
A tuple containing the names of all actions currently registered in the Neuro API.
- Return type:
Note
This method provides a snapshot of registered actions at the time of calling.
Get names of currently registered actions.
registered = api.get_registered() print(f"Available actions: {', '.join(registered)}")
Abstract Methods
These methods must be implemented in your game-specific subclass:
- abstractmethod async AbstractNeuroAPI.handle_action(action: NeuroAction) None
Handle an Action request from Neuro.
- Parameters:
action (NeuroAction) – Parsed Neuro action request data.
Warning
Should call
send_action_resultwith this action’s id as soon as scheduling action processing is complete, or else Neuro will be stuck frozen, waiting.Required implementation: Process action requests from Neuro.
This is the main method where your game logic handles Neuro’s actions.
async def handle_action(self, action: NeuroAction): try: # Parse action data if present data = None if action.data: data = json.loads(action.data) # Validate action if action.name not in self.get_registered(): await self.send_action_result( action.id_, False, f"Unknown action: {action.name}" ) return # Execute action based on name if action.name == "move_player": success = await self.execute_move(data["direction"]) message = "Moved successfully" if success else "Move failed" elif action.name == "attack": success = await self.execute_attack() message = "Attack executed" if success else "Attack failed" else: success = False message = f"Unhandled action: {action.name}" # Always send result await self.send_action_result(action.id_, success, message) except Exception as e: # Handle errors gracefully await self.send_action_result( action.id_, False, f"Action failed: {str(e)}" )
Websocket Methods (from AbstractNeuroAPIClient)
These must be implemented to handle websocket communication:
- abstractmethod async AbstractNeuroAPI.write_to_websocket(data: str) None
Abstract method to write a message to the websocket.
This method must be implemented by subclasses to define the specific mechanism for sending data over a websocket.
- Parameters:
data (str) – The message to be sent over the websocket.
- abstractmethod async AbstractNeuroAPI.read_from_websocket() bytes | bytearray | memoryview | str
Abstract method to read a message from the websocket.
This method must be implemented by subclasses to define the specific mechanism for receiving data from a websocket.
- Returns:
The message received from the websocket, supporting anything
orjson.loadscan handle.- Return type:
bytes | bytearray | memoryview | str
Game Automation Methods
These methods handle automated game launching (most games won’t need these):
- async AbstractNeuroAPI.send_shutdown_ready() None
Send shutdown ready response.
This is part of the game automation API, which will only be used for games that Neuro can launch by herself. As such, most games will not need to implement this.
This should be sent as a response to a graceful or an imminent shutdown request, after progress has been saved. After this is sent, Neuro will close the game herself by terminating the process, so to reiterate you must definitely ensure that progress has already been saved.
- Raises:
UnicodeDecodeError – If data is unable to be decoded (though this is unlikely to happen).
orjson.JSONEncodeError – If unable to encode JSON data.
- async AbstractNeuroAPI.handle_graceful_shutdown_request(wants_shutdown: bool) None
Handle a graceful shutdown request from Neuro.
This is part of the game automation API, which will only be used for games that Neuro can launch by herself. As such, most games will not need to implement this.
This message will be sent when Neuro decides to stop playing a game, or upon manual intervention from the dashboard. You should create or identify graceful shutdown points where the game can be closed gracefully after saving progress. You should store the latest received wants_shutdown value, and if it is true when a graceful shutdown point is reached, you should save the game and quit to main menu, then send back a shutdown ready message.
- Parameters:
wants_shutdown (bool) – Whether the game should shutdown at the next graceful shutdown point. - If True: Shutdown is requested - If False: Cancel the prior shutdown request
Warning
Please don’t actually close the game, just quit to main menu. Neuro will close the game herself.
Note
Base implementation sends that shutdown is ready.
- async AbstractNeuroAPI.handle_immediate_shutdown() None
Handle immediate shutdown alert from Neuro.
This is part of the game automation API, which will only be used for games that Neuro can launch by herself. As such, most games will not need to implement this.
This message will be sent when the game needs to be shutdown immediately. You have only a handful of seconds to save as much progress as possible. After you have saved, you can send back a shutdown ready message.
Warning
Please don’t actually close the game, just save the current progress that can be saved. Neuro will close the game herself.
Note
Base implementation sends that shutdown is ready.
Message Processing
- async AbstractNeuroAPI.read_message() None
Read message from Neuro websocket.
You should call this function in a loop as long as the websocket is still connected.
Automatically handles actions/reregister_all commands.
Calls
handle_graceful_shutdown_requestandhandle_immediate_shutdownfor graceful and immediate shutdown requests respectively.Calls
handle_actionfor action commands.Calls
handle_unknown_commandfor any other command.- Raises:
ValueError – If extra keys in action command data or missing keys in action command data.
TypeError – If action command key type mismatch
Note
Does not catch any exceptions
read_raw_server_messageraises.Main message processing loop. Call this continuously while connected.
The method automatically handles:
actioncommands → callshandle_action()actions/reregister_all→ re-registers all current actionsshutdown/graceful→ callshandle_graceful_shutdown_request()shutdown/immediate→ callshandle_immediate_shutdown()Unknown commands → calls
handle_unknown_command()
Complete Usage Example
Here’s a complete example of implementing a Neuro API client:
import asyncio
import json
import websockets
from neuro_api.api import AbstractNeuroAPI, NeuroAction
from neuro_api.command import Action
class MyGameAPI(AbstractNeuroAPI):
def __init__(self, websocket):
super().__init__("My Awesome Game")
self.websocket = websocket
self.player_position = {"x": 0, "y": 0}
self.player_health = 100
# Required websocket methods
async def write_to_websocket(self, data: str) -> None:
await self.websocket.send(data)
async def read_from_websocket(self) -> str:
return await self.websocket.recv()
# Required action handler
async def handle_action(self, action: NeuroAction) -> None:
try:
success = False
message = ""
if action.name == "move":
data = json.loads(action.data) if action.data else {}
direction = data.get("direction", "north")
success = await self.move_player(direction)
message = f"Moved {direction}" if success else "Move blocked"
elif action.name == "heal":
success = await self.heal_player()
message = "Healed successfully" if success else "No healing items"
elif action.name == "status":
success = True
message = f"Health: {self.player_health}, Position: {self.player_position}"
else:
message = f"Unknown action: {action.name}"
await self.send_action_result(action.id_, success, message)
except Exception as e:
await self.send_action_result(
action.id_,
False,
f"Error executing action: {str(e)}"
)
# Game logic methods
async def move_player(self, direction: str) -> bool:
moves = {
"north": (0, 1), "south": (0, -1),
"east": (1, 0), "west": (-1, 0)
}
if direction in moves:
dx, dy = moves[direction]
self.player_position["x"] += dx
self.player_position["y"] += dy
# Send context about the move
await self.send_context(
f"Player moved {direction} to {self.player_position}"
)
return True
return False
async def heal_player(self) -> bool:
if self.player_health < 100:
self.player_health = min(100, self.player_health + 25)
return True
return False
async def initialize_game(self):
# Send startup command
await self.send_startup_command()
# Register available actions
actions = [
Action(
name="move",
description="Move the player in a direction",
schema={
"type": "object",
"properties": {
"direction": {
"type": "string",
"enum": ["north", "south", "east", "west"]
}
},
"required": ["direction"]
}
),
Action("heal", "Heal the player character"),
Action("status", "Check player status")
]
await self.register_actions(actions)
# Send initial context
await self.send_context("Game initialized, player ready for action")
async def main():
uri = "ws://localhost:8765"
async with websockets.connect(uri) as websocket:
api = MyGameAPI(websocket)
await api.initialize_game()
# Main game loop
try:
while True:
await api.read_message()
except websockets.exceptions.ConnectionClosed:
print("Connection to Neuro closed")
if __name__ == "__main__":
asyncio.run(main())
Best Practices
- Initialization Sequence
Always follow this order when starting your game:
# 1. Send startup command (clears previous state) await api.send_startup_command() # 2. Register your actions await api.register_actions(actions) # 3. Send initial context await api.send_context("Game ready")
- Action Result Timing
Send action results immediately after validation, not after game execution:
async def handle_action(self, action: NeuroAction): # Validate first if not self.is_valid_action(action): await self.send_action_result(action.id_, False, "Invalid action") return # Send success result immediately await self.send_action_result(action.id_, True, "Action validated") # Then execute in game (this can be slow) await self.execute_action_in_game(action)
- Error Handling
Always handle errors gracefully and send appropriate results:
async def handle_action(self, action: NeuroAction): try: # Action logic here await self.send_action_result(action.id_, True, "Success") except ValidationError as e: await self.send_action_result(action.id_, False, f"Validation failed: {e}") except Exception as e: await self.send_action_result(action.id_, False, f"Unexpected error: {e}")
- Context Updates
Use context messages to keep Neuro informed about important game events:
# Good context examples await api.send_context("Player entered boss room") await api.send_context("Enemy defeated, gained 100 XP") await api.send_context("Low health warning: 15/100 HP")
- Action Design
Design actions that are atomic and clear:
# Good - specific actions Action("move_north", "Move player one step north") Action("attack_sword", "Attack with equipped sword") Action("use_health_potion", "Use a health potion from inventory") # Avoid - overly generic actions Action("do_something", "Do something in the game") Action("action", "Perform an action")
Error Handling
The API module handles various error conditions:
- Action Validation Errors
When registering actions with invalid names or schemas:
try: await api.register_actions(actions) except ValueError as e: print(f"Action registration failed: {e}")
- Command Processing Errors
When receiving malformed action commands:
# The read_message() method handles these automatically # and logs appropriate error messages
- Websocket Errors
Connection issues should be handled in your main loop:
Dependencies
This module builds upon:
neuro_api.client: Abstract websocket client interfaceneuro_api.command: Command formatting and validationneuro_api._deprecate: Deprecation utilities
License
This module is licensed under the GNU Lesser General Public License Version 3.
Note
Copyright (C) 2025 CoolCat467. This program is free software and comes with ABSOLUTELY NO WARRANTY.