Skip to content
This repository was archived by the owner on Mar 19, 2026. It is now read-only.

Commit dc428d6

Browse files
authored
Merge pull request #375 from PrefectHQ/update-print-setting
Update pretty-print setting name
2 parents 33a40cd + fd9f6b7 commit dc428d6

File tree

10 files changed

+50
-8
lines changed

10 files changed

+50
-8
lines changed

docs/guides/settings.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ cf.settings.log_level = 'DEBUG'
4545
Default: `False`
4646
- `log_all_messages`: If True, all LLM messages will be logged at the debug level.
4747
Default: `False`
48-
- `pretty_print_agent_events`: If True, a PrintHandler will be enabled and
48+
- `enable_default_print_handler`: If True, a PrintHandler will be enabled and
4949
automatically pretty-print agent events. Note that this may interfere with logging.
5050
Default: `True`
5151

docs/patterns/running-tasks.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ Handlers in ControlFlow provide a way to observe and react to events that occur
407407

408408
ControlFlow supports both synchronous and asynchronous handlers. Synchronous handlers implement the `Handler` interface, while asynchronous handlers implement the `AsyncHandler` interface. Both interfaces define methods for various events that can occur during task execution, including agent messages (and message deltas), user messages, tool calls, tool results, orchestrator sessions starting or stopping, and more.
409409

410-
ControlFlow includes a built-in `PrintHandler` that pretty-prints agent responses and tool calls to the terminal. It's used by default if `controlflow.settings.pretty_print_agent_events=True` and no other handlers are provided.
410+
ControlFlow includes a built-in `PrintHandler` that pretty-prints agent responses and tool calls to the terminal. It's used by default if `controlflow.settings.enable_default_print_handler=True` and no other handlers are provided.
411411

412412
### How handlers work
413413

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ env = [
117117
# use 4o-mini for tests by default
118118
'D:CONTROLFLOW_LLM_MODEL=openai/gpt-4o-mini',
119119
'D:CONTROLFLOW_TOOLS_VERBOSE=1',
120-
'D:CONTROLFLOW_PRETTY_PRINT_AGENT_EVENTS=0',
120+
'D:CONTROLFLOW_ENABLE_DEFAULT_PRINT_HANDLER=0',
121121
'D:CONTROLFLOW_LOG_LEVEL=DEBUG',
122122
'D:PREFECT_LOGGING_LEVEL=DEBUG',
123123
]

src/controlflow/orchestration/orchestrator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def _validate_handlers(cls, v):
7474
"""
7575
from controlflow.orchestration.print_handler import PrintHandler
7676

77-
if v is None and controlflow.settings.pretty_print_agent_events:
77+
if v is None and controlflow.settings.enable_default_print_handler:
7878
v = [PrintHandler()]
7979
return v or []
8080

src/controlflow/orchestration/print_handler.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@
3030

3131

3232
class PrintHandler(Handler):
33-
def __init__(self):
33+
def __init__(self, include_completion_tools: bool = True):
3434
self.events: dict[str, Event] = {}
3535
self.paused_id: str = None
36+
self.include_completion_tools = include_completion_tools
3637
super().__init__()
3738

3839
def update_live(self, latest: BaseMessage = None):
@@ -91,6 +92,12 @@ def on_tool_call(self, event: ToolCallEvent):
9192
self.events.clear()
9293

9394
def on_tool_result(self, event: ToolResultEvent):
95+
# skip completion tools if configured to do so
96+
if not self.include_completion_tools and event.tool_result.tool_metadata.get(
97+
"is_completion_tool"
98+
):
99+
return
100+
94101
self.events[f"tool-result:{event.tool_call['id']}"] = event
95102

96103
# # if we were paused, resume the live display

src/controlflow/settings.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
import os
33
from contextlib import contextmanager
44
from pathlib import Path
5+
from pyexpat import model
56
from typing import Any, Literal, Optional, Union
67

78
import prefect.logging.configuration
89
import prefect.settings
910
from pydantic import Field, field_validator, model_validator
1011
from pydantic_settings import BaseSettings, SettingsConfigDict
1112

13+
from controlflow.utilities.general import unwrap
14+
1215
CONTROLFLOW_ENV_FILE = os.getenv("CONTROLFLOW_ENV_FILE", "~/.controlflow/.env")
1316

1417

@@ -47,7 +50,27 @@ class Settings(ControlFlowSettings):
4750
default=False,
4851
description="If True, all LLM messages will be logged at the debug level.",
4952
)
50-
pretty_print_agent_events: bool = Field(
53+
pretty_print_agent_events: Optional[bool] = Field(
54+
default=None,
55+
description="If True, agent events will be pretty-printed.",
56+
deprecated=True,
57+
)
58+
59+
@model_validator(mode="before")
60+
def _validate_pretty_print_agent_events(cls, data: dict) -> dict:
61+
if data.get("pretty_print_agent_events") is not None:
62+
data["enable_default_print_handler"] = data["pretty_print_agent_events"]
63+
data["pretty_print_agent_events"] = None
64+
print(
65+
unwrap("""
66+
The `pretty_print_agent_events` setting is deprecated, use
67+
`enable_default_print_handler` instead. Your settings were
68+
updated.
69+
""")
70+
)
71+
return data
72+
73+
enable_default_print_handler: bool = Field(
5174
default=True,
5275
description="If True, a PrintHandler will be enabled and automatically "
5376
"pretty-print agent events. Note that this may interfere with logging.",

src/controlflow/tasks/task.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ def get_success_tool(self) -> Tool:
583583
"""
584584
options = {}
585585
instructions = []
586+
metadata = {"is_completion_tool": True}
586587
result_schema = None
587588

588589
# if the result_type is a tuple of options, then we want the LLM to provide
@@ -648,6 +649,7 @@ def succeed(**kwargs) -> str:
648649
description=f"Mark task {self.id} as successful.",
649650
instructions="\n\n".join(instructions) or None,
650651
parameters=result_schema.model_json_schema(),
652+
metadata=metadata,
651653
)
652654

653655
# for all other results, we create a single `result` kwarg to capture the result
@@ -666,6 +668,7 @@ def succeed(**kwargs) -> str:
666668
description=f"Mark task {self.id} as successful.",
667669
instructions="\n\n".join(instructions) or None,
668670
include_return_description=False,
671+
metadata=metadata,
669672
)
670673
def succeed(task_result: result_schema) -> str: # type: ignore
671674
if self.is_successful():
@@ -690,6 +693,7 @@ def succeed(task_result: result_schema) -> str: # type: ignore
690693
description=f"Mark task {self.id} as successful.",
691694
instructions="\n\n".join(instructions) or None,
692695
include_return_description=False,
696+
metadata=metadata,
693697
)
694698
def succeed() -> str:
695699
self.mark_successful()

src/controlflow/tools/tools.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def from_function(
113113
instructions: Optional[str] = None,
114114
include_param_descriptions: bool = True,
115115
include_return_description: bool = True,
116+
metadata: Optional[dict] = None,
116117
**kwargs,
117118
):
118119
name = name or fn.__name__
@@ -190,6 +191,7 @@ def from_function(
190191
parameters=parameters,
191192
fn=fn,
192193
instructions=instructions,
194+
metadata=metadata or {},
193195
**kwargs,
194196
)
195197

@@ -205,7 +207,7 @@ def from_lc_tool(cls, tool: langchain_core.tools.BaseTool, **kwargs):
205207
)
206208

207209
def serialize_for_prompt(self) -> dict:
208-
return self.model_dump(include={"name", "description"})
210+
return self.model_dump(include={"name", "description", "metadata"})
209211

210212

211213
def tool(
@@ -216,6 +218,7 @@ def tool(
216218
instructions: Optional[str] = None,
217219
include_param_descriptions: bool = True,
218220
include_return_description: bool = True,
221+
metadata: Optional[dict] = None,
219222
**kwargs,
220223
) -> Tool:
221224
"""
@@ -225,6 +228,7 @@ def tool(
225228
instructions=instructions,
226229
include_param_descriptions=include_param_descriptions,
227230
include_return_description=include_return_description,
231+
metadata=metadata or {},
228232
)
229233
if fn is None:
230234
return functools.partial(tool, name=name, description=description, **kwargs)
@@ -298,6 +302,7 @@ class ToolResult(ControlFlowModel):
298302
result: Any = Field(exclude=True, repr=False)
299303
str_result: str = Field(repr=False)
300304
is_error: bool = False
305+
tool_metadata: dict = {}
301306

302307

303308
def handle_tool_call(
@@ -339,6 +344,7 @@ def handle_tool_call(
339344
result=fn_output,
340345
str_result=output_to_string(fn_output),
341346
is_error=is_error,
347+
tool_metadata=tool.metadata if tool else {},
342348
)
343349

344350

@@ -379,4 +385,5 @@ async def handle_tool_call_async(tool_call: ToolCall, tools: list[Tool]) -> Any:
379385
result=fn_output,
380386
str_result=output_to_string(fn_output),
381387
is_error=is_error,
388+
tool_metadata=tool.metadata if tool else {},
382389
)

tests/fixtures/controlflow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
@pytest.fixture(autouse=True, scope="session")
1212
def temp_controlflow_settings():
1313
with temporary_settings(
14-
pretty_print_agent_events=False,
14+
enable_default_print_handler=False,
1515
log_all_messages=True,
1616
log_level="DEBUG",
1717
orchestrator_max_agent_turns=10,

tests/utilities/test_testing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ def test_record_task_events(default_fake_llm):
4747
tool_call_id="call_ZEPdV8mCgeBe5UHjKzm6e3pe",
4848
str_result='Task #12345 ("say hello") marked successful.',
4949
is_error=False,
50+
tool_metadata={"is_completion_tool": True},
5051
)

0 commit comments

Comments
 (0)