Agents

In UFO, there are four types of agents: HostAgent, AppAgent, FollowerAgent, and EvaluationAgent. Each agent has a specific role in the UFO system and is responsible for different aspects of the user interaction process:

Agent Description
HostAgent Decomposes the user request into sub-tasks and selects the appropriate application to fulfill the request.
AppAgent Executes actions on the selected application.
FollowerAgent Follows the user's instructions to complete the task.
EvaluationAgent Evaluates the completeness of a session or a round.

In the normal workflow, only the HostAgent and AppAgent are involved in the user interaction process. The FollowerAgent and EvaluationAgent are used for specific tasks.

Please see below the orchestration of the agents in UFO:

Main Components

An agent in UFO is composed of the following main components to fulfill its role in the UFO system:

Component Description
State Represents the current state of the agent and determines the next action and agent to handle the request.
Memory Stores information about the user request, application state, and other relevant data.
Blackboard Stores information shared between agents.
Prompter Generates prompts for the language model based on the user request and application state.
Processor Processes the workflow of the agent, including handling user requests, executing actions, and memory management.

Reference

Below is the reference for the Agent class in UFO. All agents in UFO inherit from the Agent class and implement necessary methods to fulfill their roles in the UFO system.

Bases: ABC

The BasicAgent class is the abstract class for the agent.

Initialize the BasicAgent.

Parameters:
  • name (str) –

    The name of the agent.

Source code in agents/agent/basic.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def __init__(self, name: str) -> None:
    """
    Initialize the BasicAgent.
    :param name: The name of the agent.
    """
    self._step = 0
    self._complete = False
    self._name = name
    self._status = self.status_manager.CONTINUE.value
    self._register_self()
    self.retriever_factory = retriever.RetrieverFactory()
    self._memory = Memory()
    self._host = None
    self._processor: Optional[BaseProcessor] = None
    self._state = None
    self.Puppeteer: puppeteer.AppPuppeteer = None

blackboard: Blackboard property

Get the blackboard.

Returns:
  • Blackboard

    The blackboard.

host: HostAgent property writable

Get the host of the agent.

Returns:
  • HostAgent

    The host of the agent.

memory: Memory property

Get the memory of the agent.

Returns:
  • Memory

    The memory of the agent.

name: str property

Get the name of the agent.

Returns:
  • str

    The name of the agent.

processor: BaseProcessor property writable

Get the processor.

Returns:
  • BaseProcessor

    The processor.

state: AgentState property

Get the state of the agent.

Returns:
  • AgentState

    The state of the agent.

status: str property writable

Get the status of the agent.

Returns:
  • str

    The status of the agent.

status_manager: AgentStatus property

Get the status manager.

Returns:
  • AgentStatus

    The status manager.

step: int property writable

Get the step of the agent.

Returns:
  • int

    The step of the agent.

add_memory(memory_item)

Update the memory of the agent.

Parameters:
  • memory_item (MemoryItem) –

    The memory item to add.

Source code in agents/agent/basic.py
185
186
187
188
189
190
def add_memory(self, memory_item: MemoryItem) -> None:
    """
    Update the memory of the agent.
    :param memory_item: The memory item to add.
    """
    self._memory.add_memory_item(memory_item)

build_experience_retriever()

Build the experience retriever.

Source code in agents/agent/basic.py
326
327
328
329
330
def build_experience_retriever(self) -> None:
    """
    Build the experience retriever.
    """
    pass

build_human_demonstration_retriever()

Build the human demonstration retriever.

Source code in agents/agent/basic.py
332
333
334
335
336
def build_human_demonstration_retriever(self) -> None:
    """
    Build the human demonstration retriever.
    """
    pass

build_offline_docs_retriever()

Build the offline docs retriever.

Source code in agents/agent/basic.py
314
315
316
317
318
def build_offline_docs_retriever(self) -> None:
    """
    Build the offline docs retriever.
    """
    pass

build_online_search_retriever()

Build the online search retriever.

Source code in agents/agent/basic.py
320
321
322
323
324
def build_online_search_retriever(self) -> None:
    """
    Build the online search retriever.
    """
    pass

clear_memory()

Clear the memory of the agent.

Source code in agents/agent/basic.py
199
200
201
202
203
def clear_memory(self) -> None:
    """
    Clear the memory of the agent.
    """
    self._memory.clear()

create_puppeteer_interface()

Create the puppeteer interface.

Source code in agents/agent/basic.py
237
238
239
240
241
def create_puppeteer_interface(self) -> puppeteer.AppPuppeteer:
    """
    Create the puppeteer interface.
    """
    pass

delete_memory(step)

Delete the memory of the agent.

Parameters:
  • step (int) –

    The step of the memory item to delete.

Source code in agents/agent/basic.py
192
193
194
195
196
197
def delete_memory(self, step: int) -> None:
    """
    Delete the memory of the agent.
    :param step: The step of the memory item to delete.
    """
    self._memory.delete_memory_item(step)

get_cls(name) classmethod

Retrieves an agent class from the registry.

Parameters:
  • name (str) –

    The name of the agent class.

Returns:
  • Type['BasicAgent']

    The agent class.

Source code in agents/agent/basic.py
353
354
355
356
357
358
359
360
@classmethod
def get_cls(cls, name: str) -> Type["BasicAgent"]:
    """
    Retrieves an agent class from the registry.
    :param name: The name of the agent class.
    :return: The agent class.
    """
    return AgentRegistry().get_cls(name)

get_prompter() abstractmethod

Get the prompt for the agent.

Returns:
  • str

    The prompt.

Source code in agents/agent/basic.py
124
125
126
127
128
129
130
@abstractmethod
def get_prompter(self) -> str:
    """
    Get the prompt for the agent.
    :return: The prompt.
    """
    pass

get_response(message, namescope, use_backup_engine, configs=configs) classmethod

Get the response for the prompt.

Parameters:
  • message (List[dict]) –

    The message for LLMs.

  • namescope (str) –

    The namescope for the LLMs.

  • use_backup_engine (bool) –

    Whether to use the backup engine.

Returns:
  • str

    The response.

Source code in agents/agent/basic.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
@classmethod
def get_response(
    cls,
    message: List[dict],
    namescope: str,
    use_backup_engine: bool,
    configs=configs,
) -> str:
    """
    Get the response for the prompt.
    :param message: The message for LLMs.
    :param namescope: The namescope for the LLMs.
    :param use_backup_engine: Whether to use the backup engine.
    :return: The response.
    """
    response_string, cost = llm_call.get_completion(
        message, namescope, use_backup_engine=use_backup_engine, configs=configs
    )
    return response_string, cost

handle(context)

Handle the agent.

Parameters:
  • context (Context) –

    The context for the agent.

Source code in agents/agent/basic.py
224
225
226
227
228
229
def handle(self, context: Context) -> None:
    """
    Handle the agent.
    :param context: The context for the agent.
    """
    self.state.handle(self, context)

message_constructor() abstractmethod

Construct the message.

Returns:
  • List[Dict[str, Union[str, List[Dict[str, str]]]]]

    The message.

Source code in agents/agent/basic.py
132
133
134
135
136
137
138
@abstractmethod
def message_constructor(self) -> List[Dict[str, Union[str, List[Dict[str, str]]]]]:
    """
    Construct the message.
    :return: The message.
    """
    pass

print_response()

Print the response.

Source code in agents/agent/basic.py
338
339
340
341
342
def print_response(self) -> None:
    """
    Print the response.
    """
    pass

process(context)

Process the agent.

Source code in agents/agent/basic.py
231
232
233
234
235
def process(self, context: Context) -> None:
    """
    Process the agent.
    """
    pass

process_asker(ask_user=True)

Ask for the process.

Parameters:
  • ask_user (bool, default: True ) –

    Whether to ask the user for the questions.

Source code in agents/agent/basic.py
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
def process_asker(self, ask_user: bool = True) -> None:
    """
    Ask for the process.
    :param ask_user: Whether to ask the user for the questions.
    """
    if self.processor:
        question_list = self.processor.question_list

        if ask_user:
            utils.print_with_color(
                "Could you please answer the following questions to help me understand your needs and complete the task?",
                "yellow",
            )

        for index, question in enumerate(question_list):
            if ask_user:
                answer = question_asker(question, index + 1)
                if not answer.strip():
                    continue
                qa_pair = {"question": question, "answer": answer}

                utils.append_string_to_file(
                    configs["QA_PAIR_FILE"], json.dumps(qa_pair)
                )

            else:
                qa_pair = {
                    "question": question,
                    "answer": "The answer for the question is not available, please proceed with your own knowledge or experience, or leave it as a placeholder. Do not ask the same question again.",
                }

            self.blackboard.add_questions(qa_pair)

process_comfirmation() abstractmethod

Confirm the process.

Source code in agents/agent/basic.py
283
284
285
286
287
288
@abstractmethod
def process_comfirmation(self) -> None:
    """
    Confirm the process.
    """
    pass

process_resume()

Resume the process.

Source code in agents/agent/basic.py
243
244
245
246
247
248
def process_resume(self) -> None:
    """
    Resume the process.
    """
    if self.processor:
        self.processor.resume()

reflection()

TODO: Reflect on the action.

Source code in agents/agent/basic.py
205
206
207
208
209
210
def reflection(self) -> None:
    """
    TODO:
    Reflect on the action.
    """
    pass

response_to_dict(response) staticmethod

Convert the response to a dictionary.

Parameters:
  • response (str) –

    The response.

Returns:
  • Dict[str, str]

    The dictionary.

Source code in agents/agent/basic.py
160
161
162
163
164
165
166
167
@staticmethod
def response_to_dict(response: str) -> Dict[str, str]:
    """
    Convert the response to a dictionary.
    :param response: The response.
    :return: The dictionary.
    """
    return utils.json_parser(response)

set_state(state)

Set the state of the agent.

Parameters:
  • state (AgentState) –

    The state of the agent.

Source code in agents/agent/basic.py
212
213
214
215
216
217
218
219
220
221
222
def set_state(self, state: AgentState) -> None:
    """
    Set the state of the agent.
    :param state: The state of the agent.
    """

    assert issubclass(
        type(self), state.agent_class()
    ), f"The state is only for agent type of {state.agent_class()}, but the current agent is {type(self)}."

    self._state = state