MCPcopy
hub / github.com/langroid/langroid / step_async

Method step_async

langroid/agent/task.py:1303–1405  ·  view source on GitHub ↗

A single "turn" in the task conversation: The "allowed" responders in this turn (which can be either the 3 "entities", or one of the sub-tasks) are tried in sequence, until a _valid_ response is obtained; a _valid_ response is one that contributes to the task, either

(self, turns: int = -1)

Source from the content-addressed store, hash-verified

1301 return self.pending_message
1302
1303 async def step_async(self, turns: int = -1) -> ChatDocument | None:
1304 """
1305 A single "turn" in the task conversation: The "allowed" responders in this
1306 turn (which can be either the 3 "entities", or one of the sub-tasks) are
1307 tried in sequence, until a _valid_ response is obtained; a _valid_
1308 response is one that contributes to the task, either by ending it,
1309 or producing a response to be further acted on.
1310 Update `self.pending_message` to the latest valid response (or NO_ANSWER
1311 if no valid response was obtained from any responder).
1312
1313 Args:
1314 turns (int): number of turns to process. Typically used in testing
1315 where there is no human to "quit out" of current level, or in cases
1316 where we want to limit the number of turns of a delegated agent.
1317
1318 Returns (ChatDocument|None):
1319 Updated `self.pending_message`. Currently the return value is not used
1320 by the `task.run()` method, but we return this as a convenience for
1321 other use-cases, e.g. where we want to run a task step by step in a
1322 different context.
1323 """
1324 self.is_done = False
1325 parent = self.pending_message
1326 recipient = (
1327 ""
1328 if self.pending_message is None
1329 else self.pending_message.metadata.recipient
1330 )
1331 if not self._valid_recipient(recipient):
1332 logger.warning(f"Invalid recipient: {recipient}")
1333 error_doc = ChatDocument(
1334 content=f"Invalid recipient: {recipient}",
1335 metadata=ChatDocMetaData(
1336 sender=Entity.AGENT,
1337 sender_name=Entity.AGENT,
1338 ),
1339 )
1340 self._process_valid_responder_result(Entity.AGENT, parent, error_doc)
1341 return error_doc
1342
1343 responders: List[Responder] = self.non_human_responders_async.copy()
1344
1345 if (
1346 Entity.USER in self.responders
1347 and not self.human_tried
1348 and not self.agent.has_tool_message_attempt(self.pending_message)
1349 ):
1350 # Give human first chance if they haven't been tried in last step,
1351 # and the msg is not a tool-call attempt;
1352 # This ensures human gets a chance to respond,
1353 # other than to a LLM tool-call.
1354 # When there's a tool msg attempt we want the
1355 # Agent to be the next responder; this only makes a difference in an
1356 # interactive setting: LLM generates tool, then we don't want user to
1357 # have to respond, and instead let the agent_response handle the tool.
1358 responders.insert(0, Entity.USER)
1359
1360 found_response = False

Callers 2

run_asyncMethod · 0.95
test_task_step_asyncFunction · 0.95

Calls 14

_valid_recipientMethod · 0.95
_can_respondMethod · 0.95
log_messageMethod · 0.95
response_asyncMethod · 0.95
_is_done_responseMethod · 0.95
validMethod · 0.95
ChatDocumentClass · 0.90
ChatDocMetaDataClass · 0.90

Tested by 1

test_task_step_asyncFunction · 0.76