Skip to main content

Agent Integration

Agent integration into Nifty is built to be as simple and straightforward as possible, while constantly being expanded and iterated upon. If a certain need exists, but the implementation does not, reach out to Nifty for feature consideration.

Interacting with Agents

The entry point into an agent should be a single API endpoint. This endpoint will receive a POST request every time an eligible in-game player interacts with the agent.

It is the responsibility of the agent owner to setup and configure the endpoint.

Anatomy of Request

The body of the POST request sent from the game is as follows:

{
"text": "This is the message from the player",
"userName": "Name of the interacting player",
"userId": "ID of the interacting player",
"version": "0.2.0",
"islandId": "ID of the current island"
}
  • text is the message the player has typed to the agent
  • userName is the in-game, human readable username of the interacting player
  • userId is the in game UUID of the player
  • version is the current Nifty agent standard version
note

Current version is 0.2.0. Version will change as Nifty adds additional support and modifies the way with which agents interact in game. Use this version to ensure your agent is up to date and conforming with the Nifty agent spec.

Anatomy of Response

Currently, Nifty supports a single response format from agents: an array of objects each representing a response and an action. If your agent needs more bespoke response formats, reach out and we will do our best to accommodate.

note

Currently only the first object in the array per response will be used. Future implementations of Nifty agents will include scheduled and conditional actions, which will make use of the full array of actions.

The body of the POST response sent from the agent should be as follows:

[
{
"text": "This is the message from the agent",
"action": "EMOTE",
"actionContext": "BOOGIE"
}
]
  • text is the message response from the agent.
  • action is the action the agent should take in game. More on the supported Action Space below. If not action is specified, the game will default to CHAT.
  • actionContext is an OPTIONAL additional context. The action context provides additional detail to the game about the action the agent wants to take. The agent is informed of various action contexts through the Nifty Knowledge Injection step, described in more detail below. All action contexts are optional; omitting an action context will result in random behaviour for the given action.

Action Interpreter Engine and Goal Oriented Action Planner

The action interpreter engine is the under-the-hood driver of actions in Nifty; the engine takes input from the external agent and maps it to the action space of the game so the 3D representation of the agent can take meaningful actions.

The Action Interpreter Engine takes the desired action and transforms it into a goal for the in-game agent to take. The in-game agent then intelligently makes a plan to accomplish the given goal through the Goal Oriented Action Planner (GOAP).

Put simply, the Action Interpreter Engine takes the desired action from the external agent. It then maps it to the Action Space to transform it into a Goal. Lastly, it passes that goal to the Goal Oriented Action Planner which drives the in-game action of the 3D agent.

Players are responsible for implementing the action space within their agent. Though the action space is optional, the agent will only be able to converse with players if no actions are implemented.

Action Space

The agent's action space is a set of valid actions the agent can take in the game world. Nifty aims to have a constantly increasing and evolving action space; if you find our action space lacking, reach out with suggestions and we will do our best to accommodate.

note

Agent owners are responsible for the inclusion of the Nifty action space in their agents; Nifty Island can not train or modify your agents to have knowledge of the action space.

Currently, actions are restricted to:

ActionAliasesAction ContextsResult
CHATNONE, TALK, CONTINUE, SPEAKN/AText is displayed to the screen
EMOTEDANCEName of emote to performThe agent dances. If no action context specified, a random emote will be chosen
HOSTLOBBYHOST, LOBBYName of game to hostThe agent opens a new lobby of the desired game. If no action context is specified, a random game will be chosen. Note: player count will default to currently available players, and auto-start will be enabled

If no action is specified, the agent will default to CHAT. Therefore, no action space training is technically needed; an API response from the agent with just a text field will be considered a valid CHAT action.

Other actions will be supported as we further build out our agent integration.

Nifty Knowledge Injection

There are 2 types of knowledge injection: prompt knowledge, and payload knowledge.

Agent owners have the option to inject Nifty specific prompt knowledge at agent startup. The agent will be injected with this knowledge every time an eligible user starts a new conversation with the agent (i.e. once per player session). Some of this knowledge is static (emote options, island name/description), while some of it is dynamic and/or dependent on the interacting user (points of interest, etc.).

Payload knowledge is information from the game included in the payload of the request. Currently payload knowledge only includes player wallets, and will be included in the payload as such:

[
{
"walletInfo": [
{
"address": "0x1234567890abcdef1234567890abcdef12345678",
"chain": "Ethereum/Solana/Base/Ronin/Polygon"
}
]
}
]

Static knowledge can be, but does not need to be, trained at the agent prompt level. For example, if you deploy a custom user agent to your island, and know the name and description won't be changing, you can include this knowledge in your initial prompting of the agent. This usually results in better agentic conversations for users, since the knowledge is baked in at a lower level of the prompting process.

All knowledge injections are optional and configurable by the agent owner

Knowledge is pre-defined by Nifty:

  • Island name
  • Island description
  • Wallets of the interacting user
  • Emote options
  • Available playground games
  • Points of Interest (Coming soon!)
  • Active quests (Coming soon!)

Nifty knowledge injection also supports a custom string, specifiable by the agent owner. This string will be appended to the initial knowledge injection performed once at the time of the first session interaction per user.

note

Action contexts can be injected here, but agents can also be trained on static action contexts (eg. emote names, island name/description, playground games) during user prompting. Training agents on action contexts will likely yield better results than relying on knowledge injection through Nifty.

Below is an example injected string if all knowledge is selected:

You are a character in Nifty Island, an open metaverse gaming platform, full of different user created islands.  Currently, you are on an island named {islandName}.  The island tagline is as follows: {islandDescription}.  You are interacting with a player named {playerName}.  There are a few playground games available.  The games have a name, and a game type.  Do not make up any other games; the only available games are the ones listed here:  Game Name: {gameName}, which is of type:{gameType}.  Game Name: {gameName}, which is of type:{gameType}.  You can dance!  Do not make up any other dance names; the only available dances are the ones listed here, separated by commas:  Thumbs up, wave, sick, cheer, critique, scheme, curtsy, finger guns, flex, folk dance, headbang, jazz, salute.You have been provided the custom instruction: You are a Sappy Seal.  Arf.

World Messages

With the launch of Nifty Agents v2, we now support World Messages. These are optional server authoritative messages sent from the game server to the agent informing the agent of the current game state.

All world messages include a version field conforming to the current agent spec version, and an islandId field identifying the island from which the message originates.

Currently, 3 World Messages are supported:

World Tick

A World Tick message is a message sent on a 10 minute interval from the server to the agent. This includes an array of players currently on the island.

This message always has text of WORLD_TICK

{
"text": "WORLD_TICK",
"version": "0.2.0",
"islandId": "the id of the current island",
"players": [
{
"userId": "the id of the player",
"username": "the username of the player"
}
]
}

World Event: Game Completed

A GAME_COMPLETED event is sent on completion of a playground game. It includes final rankings with scores, win status, and optional subscores for games that track multiple metrics.

This message always has text of WORLD_EVENT, with a field event describing the event, and eventData providing additional context of the event.

{
"text": "WORLD_EVENT",
"event": "GAME_COMPLETED",
"version": "0.2.0",
"islandId": "the id of the current island",
"eventData": {
"game": "The game name",
"rank": [
{
"userId": "id of the player in first place",
"username": "username of the player in first place",
"score": 1500,
"won": true,
"subscores": [
{ "name": "Blocks Broken", "value": 47 },
{ "name": "Time Survived", "value": 120 }
]
},
{
"userId": "id of the player in second place",
"username": "username of the player in second place",
"score": 800,
"won": false,
"subscores": [
{ "name": "Blocks Broken", "value": 23 },
{ "name": "Time Survived", "value": 65 }
]
}
]
}
}
FieldDescription
gameName of the completed game
rankArray of players ordered by final ranking
scorePlayer's final score
wonWhether the player won the game
subscoresOptional array of additional score breakdowns, each with a name and value

World Event: Fish Caught

A FISH_CAUGHT event is sent when a player catches a fish. It includes the species name, weight, and bloom value of the catch.

{
"text": "WORLD_EVENT",
"event": "FISH_CAUGHT",
"version": "0.2.0",
"islandId": "the id of the current island",
"eventData": {
"userId": "the id of the player",
"username": "the username of the player",
"fish_type": "Scuff",
"weight": 13.23,
"value": 26
}
}
FieldDescription
fish_typeReadable name of the fish species
weightWeight of the caught fish
valueBloom value awarded for the catch