Skip to main content

Conversations

note

This page assumes you are already familiar with how get hold of an api_key and org_id and how to install the Engage Smarter Python library. If not, turn to the Getting Started tutorial.

Conceptual overview

The Engage Smarter AI Conversations API is the main API for interacting with agents on the platform.

Conversations are threads of messages between a user and an AI agent on the platform linked by a common conversation_id. The platform contains a record of the conversation history, meaning the API is stateful. When a new user message is sent to an agent via the Conversations API, the platform retrieves the previous conversation history and adds the latest user message. The agent then responds to the latest user message, using the existing conversation history as additional context.

The platform keeps track of which conversation a message is part of by enforcing that a conversation_id be sent with every user message to the Conversations API.

note

There is also the Runs API which expects a full message history between the User and the Agent to always be sent rather than just the latest user message. This is comparable to the OpenAI Chat Completion API. See the Runs section for more details.

Pre-requisites

First, we initialise the Engage Smarter Python Client.

import os

from engagesmarter import Client

api_key = os.getenv("ENGAGE_SMARTER_API_KEY")
org_id = os.getenv("ENGAGE_SMARTER_ORG_ID")

client = Client(
api_key=api_key,
org_id=org_id,
)

Creating a new conversation

To have a conversation with an AI agent, we first need to request a conversation_id to use with every subsequent request in the same conversation. To do this, we use the create method which returns a ConversationReadFull object with an id field representing the conversation_id.

conversation = client.conversations.create()
conversation_id = conversation.id

When we create a conversation, we may also want to pass in metadata to record additional information in the platform for us to refer to later. To do this we pass in a ConversationCreate object to the create method. We can use the data field for additional metadata and the source field to record where the API is being called from, for instance a particular chat integration.

When we get back the ConversationReadFull object, we can see as well as the id field, we also have a data field and source field with the data we passed in.

from engagesmarter import ConversationCreate

conversation_data = ConversationCreate(
data={"additional": "data", "can": "be", "added": "here"}, source="test_source"
)
conversation = client.conversations.create(conversation=conversation_data)
conversation_id = conversation.id

print(conversation.data)
print(conversation.source)
    {'additional': 'data', 'can': 'be', 'added': 'here'}
test_source
tip

The additional data and source within a conversation may be useful for linking a conversation to a particular user or ticket in your system or from a particular system source.

note

The Engage Smarter AI Platform also has a tags mechanism for labelling either conversations or runs.

Interacting with an agent

Now that we have our conversation initialised with a conversation_id, we can start to interact with an agent.

Let's send a first message to the agent. We'll speak to an agent which is an expert in pensions.

from engagesmarter import UserMessage

AGENT = "pensions-questions-latest"

user_message_1 = UserMessage(content="Hello, can you help me understand pensions?")

response = client.conversations.chat_with_agent(
conversation_id=conversation_id,
messages=[user_message_1],
agent=AGENT,
)
response
    [MessageRead(id='06627879-6c7c-71e1-8000-65f746de95e0', org_id='065d66dd-e3ce-7969-8000-f2372634456f', conversation_id='06627879-6031-73de-8000-484a31530cfe', run_id='06627879-61b6-7cb3-8000-471ec2e6479a', role='agent', content="Of course, I'm here to help you understand pensions! Pensions can be complex, but I'll do my best to explain them in a clear and concise way. What specific aspect of pensions would you like to know more about? Are you interested in how pensions are managed, what happens to your pension when you die, or perhaps the different options available to you when you retire? Let me know and I'll provide you with more information.", name='pensions-questions-240228-dev', user_id='065d64bc-2480-7b32-8000-bd68db1e258e', created=datetime.datetime(2024, 4, 23, 10, 4, 6, 780000))]

We get back a list of messages, in this case containing one agent message. We can see that its role is "agent" and the content is the response from the agent.

agent_message_1 = response[0]

print(agent_message_1.role)
    agent
print(agent_message_1.content)
    Of course, I'm here to help you understand pensions! Pensions can be complex, but I'll do my best to explain them in a clear and concise way. What specific aspect of pensions would you like to know more about? Are you interested in how pensions are managed, what happens to your pension when you die, or perhaps the different options available to you when you retire? Let me know and I'll provide you with more information.

Since the Conversations API is stateful, to continue the conversation all we need to do is send another user message with the same conversation_id as before. The agent on the platform knows what has already been said in the conversation and can respond to the user's latest message with that past context in mind.

user_message_2 = UserMessage(
content="Thanks, yes, I'd like some help understanding the options around transferring an old workplace pension."
)

replies = client.conversations.chat_with_agent(
conversation_id=conversation_id,
messages=[user_message_2],
agent=AGENT,
)
agent_message_2 = replies[0]
note

Notice that the user message is passed in as part of a list. This is because the API expects a list of messages to be sent in, even if there is only one message. You can in fact send multiple user messages at once to the API, and the agent will respond taking those message - plus the existing conversation history - into account.

Accessing the message history

If we want to see the full message history for a conversation, we can use the conversation_id to access it via the get_conversation_message_history method:

message_history = client.conversations.get_conversation_message_history(
conversation_id=conversation_id
)

for message in message_history:
print(f"{message.role}: {message.content[:50]} ...")
    user: Hello, can you help me understand pensions? ...
agent: Of course, I'm here to help you understand pension ...
user: Thanks, yes, I'd like some help understanding the ...

Searching your past conversations

You can search your conversations to find a specific conversation or a set of conversations that match a certain criteria. To do this, you can use the search_own_conversations method. This will return a list of ConversationRead objects that match the search criteria.

The results are paginated, meaning you will need to use the limit and offset parameters to page through the results. You can set the reversed parameter to True to reverse the order of the results.

User Conversations

The search_own_conversations method will return conversations which you as a User have had either via the Platform UI or via the Conversations API. If you have shared an API key, for instance for use in a production system, then those conversations will be included in the search results.

results = client.conversations.search_own_conversations(limit=10, offset=0)

print(len(results))
    10

Accessing or updating a conversation's metadata

We saw above that it is possible to add metadata to a conversation when it is created. We can also access conversation metadata at any time by requesting the ConversationReadFull object. This object has a data field which contains the metadata and a source field for system source information, along with other fields such as the id, created timestamp and linked org_id.

conversation_metadata = client.conversations.get_conversation_metadata(
conversation_id=conversation_id
)
print(conversation_metadata.data)
print(conversation_metadata.source)
    {'additional': 'data', 'can': 'be', 'added': 'here'}
test_source

We can also easily update this conversation metadata. Here we update only the data field, but we could also update the source field if we wanted to.

from engagesmarter import ConversationUpdate

conversation_update = ConversationUpdate(data={"different": "data"})
updated_conversation_metadata = client.conversations.update_conversation_metadata(
conversation_id=conversation_id,
conversation=conversation_update,
)
print(updated_conversation_metadata.data)
print(updated_conversation_metadata.source)
    {'different': 'data'}
test_source