Tool Use
Tool Use and Conversational ChessΒΆ
In this example, we build a conversational chess game using three agents: Player White, Player Black, and Board Proxy. The agents interact to play a game of chess, with each player taking turns to make moves. The Board Proxy manages the board state and facilitates communication between the players.
Note
Can you find a better way to handle the board state and move tracking between agents, without using globals? Give it a try! We'd love to hear your feedback on this example, either by contributing to the repository, or by reaching out to us.
OverviewΒΆ
The flow includes:
- Player White and Player Black agents for each chess player.
- Board Proxy to manage board state and relay information between players.
Agents and SkillsΒΆ
AgentsΒΆ
- Player White: The agent playing white pieces. Calls methods to get legal moves and make moves.
- Player Black: The agent playing black pieces. Operates similarly to Player White.
- Board Proxy: Manages the boardβs state and facilitates move tracking between agents.
SkillsΒΆ
Each player has access to the following skills:
- get_legal_moves: Fetches the list of legal moves in UCI format.
- make_move: Executes a move and provides feedback on the action taken.
get_legal_movesΒΆ
This function generates a list of possible legal moves from the current board state.
Content:
from typing import Annotated import chess if "BOARD" not in globals(): BOARD = chess.Board() globals()["BOARD"] = BOARD else: BOARD = globals()["BOARD"] def get_legal_moves() -> Annotated[str, "A list of legal moves in UCI format"]: """Get a list of legal moves.""" return "Possible moves are: " + ",".join( [str(move) for move in BOARD.legal_moves] )
make_moveΒΆ
Executes a chosen move and outputs the result.
- Content:
from typing import Annotated import chess # Global variables to store the board and move status. if "BOARD" not in globals(): BOARD = chess.Board() globals()["BOARD"] = BOARD else: BOARD = globals()["BOARD"] if "MADE_MOVE" not in globals(): MADE_MOVE = False globals()["MADE_MOVE"] = MADE_MOVE else: MADE_MOVE = globals()["MADE_MOVE"] def make_move( move: Annotated[str, "A move in UCI format."], ) -> Annotated[str, "Result of the move."]: """Make a move on the board.""" global MADE_MOVE try: move = chess.Move.from_uci(move) except BaseException: # pylint: disable=broad-except move = BOARD.parse_san(move) BOARD.push_uci(str(move)) # Get the piece name. piece = BOARD.piece_at(move.to_square) piece_symbol = piece.unicode_symbol() piece_name = ( chess.piece_name(piece.piece_type).capitalize() if piece_symbol.isupper() else chess.piece_name(piece.piece_type) ) MADE_MOVE = True return f"Moved {piece_name} ({piece_symbol}) from "\ f"{chess.SQUARE_NAMES[move.from_square]} to "\ f"{chess.SQUARE_NAMES[move.to_square]}."
Agent ConfigurationΒΆ
Player White and Player Black Agents:
- System Message: You are a chess player and you play as black / white. First call get_legal_moves(), to get a list of legal moves. Then call make_move(move) to make a move.
Skills: Assign
get_legal_moves
andmake_move
to each agent. Set the executor to the board proxy.
Board Proxy:
Termination Method: Set up a termination method to end the conversation after a move is made. This method resets a flag (
MADE_MOVE
) after each move to monitor the game flow.
ChatsΒΆ
The flow starts with the black player challenging the white player to a game of chess. The white player then makes the first move.
- Player Black => Player White: The black player challenges the white player to a game of chess. For the message we use the "Text" type and for content, we use:
- Player White => Board Proxy: When the white player receives the challenge, a new nested chat is triggered to get the move to play using the board proxy.
- Player Black => Board Proxy: When the black player gets a reply from the white player, a new nested chat is triggered to get the move to play using the board proxy. And the beat goes on!
Register Nested ChatsΒΆ
On each agent, set up the nested chats we defined above, to handle the flow of the game. For the white player, a nested chat is triggered when the black player makes a move. For the black player, a nested chat is triggered when the white player replies. The message to use is the board proxy's reply, after a new move is made.
Flow chats and requirementsΒΆ
- Edit Flow: Set up the flow order to start with the "Player Black => Player White" connection.
- Additional requirements: As we have seen, running the flow requires the usage of the "chess" library, so make sure to add it in the "Other" tab
Files used in this example: