For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Help on Discord
HomeGuideExamplesBAML ReferencePlaygroundAgents.mdChangelog
HomeGuideExamplesBAML ReferencePlaygroundAgents.mdChangelog
    • Overview
  • baml-cli
    • init
    • generate
    • test
    • serve
    • dev
    • fmt
  • Language Reference
    • Types
    • function
    • test
    • template_string
    • client<llm>
    • class
    • enum
    • generator
  • Generated baml_client
    • with_options(..)
    • AbortSignal / Cancellation
    • Collector
    • logging / env vars
    • AsyncClient / SyncClient
    • TypeBuilder
    • ClientRegistry
    • client Option
    • OnTick
    • Multimodal
    • Image
    • Audio
    • Pdf
    • Video
  • Attributes
    • What are attributes?
    • @alias / @@alias
    • @description / @@description
    • @skip
    • @assert
    • @check
    • Jinja in Attributes
    • @@dynamic
  • LLM Client Providers
    • Overview
    • AWS Bedrock
    • Anthropic
    • Google AI: Gemini
    • Google: Vertex
    • OpenAI
    • OpenAI Responses API
    • OpenAI from Azure
    • OpenRouter
    • openai-generic
    • Microsoft Foundry (openai-generic)
    • Cerebras (openai-generic)
    • Groq (openai-generic)
    • Hugging Face (openai-generic)
    • Keywords AI (openai-generic)
    • Llama API (openai-generic)
    • Litellm (openai-generic)
    • LM Studio (openai-generic)
    • Ollama (openai-generic)
    • Vercel AI Gateway (openai-generic)
    • Tinfoil (openai-generic)
    • TogetherAI (openai-generic)
    • Unify AI (openai-generic)
    • vLLM (openai-generic)
  • LLM Client Strategies
    • Timeout Configuration
    • Retry Policy
    • Fallback
    • Round Robin
  • Prompt Syntax
    • What is jinja?
    • Jinja Filters
    • ctx.output_format
    • ctx.client
    • _.role
    • Variables
    • Conditionals
    • Loops
  • Editor Extension Settings
    • baml.cliPath
    • baml.generateCodeOnSave
    • baml.enablePlaygroundProxy
    • baml.syncExtensionToGeneratorVersion
Help on Discord
LogoLogo
On this page
  • Quick Start
  • Common Use Cases
  • Progress Monitoring
  • Accessing Streaming “Thinking” Content
  • Debugging and Logging
  • Using with Collectors
  • Error Handling
  • Limitations
  • API Reference
  • OnTick Callback Signature
  • Integration with Function Calls
  • Related Topics
  • Best Practices
Generated baml_client

OnTick

Was this page helpful?
Edit this page
Previous

Image / Audio / Pdf / Video

Next
Built with

The onTick feature allows you to receive real-time callbacks during BAML function execution, providing access to internal state, streaming responses, and progress updates. This is particularly useful for monitoring function progress, debugging, and accessing intermediate data like “thinking” content from streaming LLM responses.

Quick Start

Python
TypeScript
Go
1from baml_client import b
2from baml_py import baml_py
3
4def on_tick(reason: str, log: baml_py.FunctionLog):
5 print(f"Tick received: {reason}")
6 print(f"Function calls: {len(log.calls) if log else 0}")
7
8# Use with async function
9result = await b.TestFunction("Hello world", baml_options={"on_tick": on_tick})

Common Use Cases

Progress Monitoring

Track the progress of long-running BAML function calls:

Python
TypeScript
Go
1from baml_client import b
2from baml_py import baml_py
3
4def progress_monitor(reason: str, log: baml_py.FunctionLog):
5 tick_count = getattr(progress_monitor, 'count', 0)
6 progress_monitor.count = tick_count + 1
7
8 print(f"Progress tick #{progress_monitor.count}: {reason}")
9
10 if log and log.calls:
11 latest_call = log.calls[-1]
12 print(f"Latest call to: {latest_call.client_name}")
13
14result = await b.ExtractResume(
15 resume_text,
16 baml_options={"on_tick": progress_monitor}
17)

Accessing Streaming “Thinking” Content

Extract intermediate “thinking” content from streaming LLM responses:

Python
TypeScript
Go
1import json
2from baml_client import b
3from baml_py import baml_py
4
5def extract_thinking(reason: str, log: baml_py.FunctionLog):
6 thinking_content = ""
7
8 if log and log.calls:
9 last_call = log.calls[-1]
10
11 # Check if it's a streaming call
12 if hasattr(last_call, "sse_responses"):
13 sse_responses = last_call.sse_responses()
14 if sse_responses:
15 for response in sse_responses:
16 try:
17 data = json.loads(response.text)
18 if "delta" in data and "thinking" in data["delta"]:
19 thinking_content += data["delta"]["thinking"]
20 except (json.JSONDecodeError, AttributeError):
21 pass
22
23 if thinking_content:
24 print(f"Thinking content: {thinking_content}")
25
26# Use with streaming function
27stream = b.stream.TestThinking(
28 "Write a story about AI",
29 baml_options={"on_tick": extract_thinking}
30)
31
32async for msg in stream:
33 pass
34
35result = await stream.get_final_response()

Debugging and Logging

Use onTick for comprehensive debugging and logging:

Python
TypeScript
Go
1from baml_client import b
2from baml_py import baml_py
3
4def debug_logger(reason: str, log: baml_py.FunctionLog):
5 print(f"=== DEBUG TICK: {reason} ===")
6
7 if log:
8 print(f"Function: {log.function_name}")
9 print(f"Log type: {log.log_type}")
10 print(f"Number of calls: {len(log.calls)}")
11
12 if log.usage:
13 print(f"Input tokens: {log.usage.input_tokens}")
14 print(f"Output tokens: {log.usage.output_tokens}")
15
16 if log.calls:
17 latest_call = log.calls[-1]
18 print(f"Latest provider: {latest_call.provider}")
19 print(f"Latest client: {latest_call.client_name}")
20
21 if latest_call.usage:
22 print(f"Call usage - Input: {latest_call.usage.input_tokens}, Output: {latest_call.usage.output_tokens}")
23
24 print("=== END DEBUG ===\n")
25
26result = await b.TestFunction("Debug this call", baml_options={"on_tick": debug_logger})

Using with Collectors

OnTick can be used alongside Collectors for comprehensive logging:

Python
TypeScript
Go
1from baml_client import b
2from baml_py import baml_py, Collector
3
4def on_tick_with_collector(reason: str, log: baml_py.FunctionLog):
5 print(f"OnTick fired: {reason}")
6
7# Create a collector alongside onTick
8collector = Collector("my-collector")
9
10result = await b.TestFunction(
11 "Hello world",
12 baml_options={
13 "on_tick": on_tick_with_collector,
14 "collector": collector
15 }
16)
17
18# Access data through both mechanisms
19print(f"Collector usage: {collector.last.usage}")

Error Handling

OnTick callbacks should handle errors gracefully. If an onTick callback throws an error, the function execution will continue:

Python
TypeScript
Go
1from baml_client import b
2from baml_py import baml_py
3
4def error_prone_tick(reason: str, log: baml_py.FunctionLog):
5 # Simulate an error condition
6 if hasattr(error_prone_tick, 'count'):
7 error_prone_tick.count += 1
8 else:
9 error_prone_tick.count = 1
10
11 if error_prone_tick.count == 5:
12 raise ValueError("Intentional error in onTick")
13
14 print(f"Tick #{error_prone_tick.count}: {reason}")
15
16# Function will complete despite callback errors
17result = await b.TestFunction("Hello world", baml_options={"on_tick": error_prone_tick})
18print("Function completed successfully despite onTick error")

Limitations

Keep these limitations in mind when using onTick:

  1. Synchronous Functions: OnTick is not supported for synchronous function calls. Attempting to use onTick with sync functions will throw an error.

  2. Error Isolation: Errors in onTick callbacks do not stop function execution, but they may not be explicitly surfaced.

API Reference

OnTick Callback Signature

Python
TypeScript
Go
1def on_tick(reason: str, log: baml_py.FunctionLog | None) -> None:
2 """
3 OnTick callback function
4
5 Args:
6 reason: The reason for the tick (currently always "Unknown")
7 log: The current function log with call information
8 """
9 pass

Integration with Function Calls

OnTick is passed via the baml_options parameter (Python) or options object (TypeScript/Go):

Python
TypeScript
Go
1# Async function call
2result = await b.FunctionName(input, baml_options={"on_tick": callback})
3
4# Streaming function call
5stream = b.stream.FunctionName(input, baml_options={"on_tick": callback})

Related Topics

  • Collector - Learn about comprehensive logging with Collectors
  • Using with_options - Configure global options for BAML functions
  • Streaming - Understand streaming function calls

Best Practices

  1. Keep Callbacks Light: OnTick callbacks should be fast and non-blocking
  2. Handle Errors Gracefully: Always include error handling in your callbacks
  3. Use with Collectors: Combine onTick with Collectors for comprehensive logging
  4. Monitor Performance: Test the performance impact for your specific use case
  5. Async Only: Remember that onTick only works with async function calls, not sync calls