Skip to content

Commit 789cb69

Browse files
authored
Merge pull request #74 from jlowin/agent-viz
Give agents greater visibility into activity
2 parents a130a95 + 65edb08 commit 789cb69

File tree

6 files changed

+27
-11
lines changed

6 files changed

+27
-11
lines changed

src/controlflow/core/controller/instruction_template.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,10 @@ class TasksTemplate(Template):
110110
111111
### Providing a result
112112
113-
Tasks may require a typed result, which is an artifact satisfying the task's objective. If a
114-
task does not require a result artifact (e.g. `result_type=None`), you must still
115-
complete its stated objective before marking the task as complete.
113+
Tasks may require a typed result, which is an artifact satisfying the
114+
task's objective. If a task does not require a result artifact (e.g.
115+
`result_type=None`), you must still complete its stated objective before
116+
marking the task as complete.
116117
117118
"""
118119
tasks: list[Task]
@@ -149,8 +150,9 @@ class CommunicationTemplate(Template):
149150
posted as messages to the thread, so you never need to write out task
150151
results as messages before marking a task as complete.
151152
152-
Note that all agents post messages with the "assistant" role, so
153-
each agent's messages are automatically prefixed with that agent's name for clarity.
153+
Note that all agents post messages with the "assistant" role, so each
154+
agent's name will be automatically prefixed to their messages. You do
155+
NOT need to include your name in your messages.
154156
155157
### Talking to human users
156158

src/controlflow/core/controller/moderators.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def classify_moderator(
2525
instructions = get_instructions()
2626
context = context or {}
2727
context.update(tasks=tasks, history=history, instructions=instructions)
28+
2829
agent = classify(
2930
context,
3031
labels=agents,

src/controlflow/core/flow.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,10 @@ def get_flow_messages(limit: int = None) -> list[MessageType]:
8181
8282
Will error if no flow is found in the context.
8383
"""
84+
if limit is None:
85+
limit = 50
8486
flow = get_flow()
8587
if flow:
86-
get_default_history().load_messages(flow.thread_id, limit=limit)
88+
return get_default_history().load_messages(flow.thread_id, limit=limit)
8789
else:
8890
return []

src/controlflow/core/task.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,16 +450,21 @@ def mark_successful(self, result: T = None, validate_upstreams: bool = True):
450450

451451
self.result = validate_result(result, self.result_type)
452452
self.set_status(TaskStatus.SUCCESSFUL)
453-
453+
if agent := ctx.get("controller_agent"):
454+
return f"{self.friendly_name()} marked successful by {agent.name}."
454455
return f"{self.friendly_name()} marked successful."
455456

456457
def mark_failed(self, message: Union[str, None] = None):
457458
self.error = message
458459
self.set_status(TaskStatus.FAILED)
460+
if agent := ctx.get("controller_agent"):
461+
return f"{self.friendly_name()} marked failed by {agent.name}."
459462
return f"{self.friendly_name()} marked failed."
460463

461464
def mark_skipped(self):
462465
self.set_status(TaskStatus.SKIPPED)
466+
if agent := ctx.get("controller_agent"):
467+
return f"{self.friendly_name()} marked skipped by {agent.name}."
463468
return f"{self.friendly_name()} marked skipped."
464469

465470

src/controlflow/llm/formatting.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ def format_text_message(message: MessageType) -> Panel:
6363
def format_assistant_message_with_tool_calls(message: AssistantMessage) -> Group:
6464
panels = []
6565
for tool_call in get_tool_calls(message):
66+
if message.role == "assistant" and message.name:
67+
title = f"Tool Call: {message.name}"
68+
else:
69+
title = "Tool Call"
70+
6671
content = Markdown(
6772
inspect.cleandoc("""
6873
🦾 Calling `{name}` with the following arguments:
@@ -74,10 +79,11 @@ def format_assistant_message_with_tool_calls(message: AssistantMessage) -> Group
7479
name=tool_call.function.name, args=tool_call.function.arguments
7580
)
7681
)
82+
7783
panels.append(
7884
Panel(
7985
content,
80-
title="[bold]Tool Call[/]",
86+
title=f"[bold]{title}[/]",
8187
subtitle=f"[italic]{format_timestamp(message.timestamp)}[/]",
8288
title_align="left",
8389
subtitle_align="right",

src/controlflow/utilities/context.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class ScopedContext:
2727
"""
2828

2929
def __init__(self, initial_value: dict = None):
30-
"""Initializes the ScopedContext with an initial valuedictionary."""
30+
"""Initializes the ScopedContext with an initial value dictionary."""
3131
self._context_storage = contextvars.ContextVar(
3232
"scoped_context_storage", default=initial_value or {}
3333
)
@@ -44,8 +44,7 @@ def __getitem__(self, key: str) -> Any:
4444

4545
def set(self, **kwargs: Any) -> None:
4646
ctx = self._context_storage.get()
47-
updated_ctx = {**ctx, **kwargs}
48-
token = self._context_storage.set(updated_ctx)
47+
token = self._context_storage.set(ctx | kwargs)
4948
return token
5049

5150
@contextmanager
@@ -74,5 +73,6 @@ def __call__(self, **kwargs: Any) -> Generator[None, None, Any]:
7473
flow=None,
7574
tasks=[],
7675
tui=None,
76+
controller_agent=None,
7777
)
7878
)

0 commit comments

Comments
 (0)