Custom Logging

Configure custom loggers and formatters for your Kern setup.

You can provide your own logging configuration to Kern, to be used instead of the default ones.

This can be useful if you need your system to log in any specific format.

Specifying a custom logging configuration

You can configure Kern to use your own logging configuration by using the configure_agno_logging function.

1import logging
2
3from kern.agent import Agent
4from kern.utils.log import configure_agno_logging, log_info
5
6# Set up a custom logger
7custom_logger = logging.getLogger("custom_logger")
8handler = logging.StreamHandler()
9formatter = logging.Formatter("[CUSTOM_LOGGER] %(levelname)s: %(message)s")
10handler.setFormatter(formatter)
11custom_logger.addHandler(handler)
12custom_logger.setLevel(logging.INFO)
13custom_logger.propagate = False
14
15# Configure Kern to use the custom logger
16configure_agno_logging(custom_default_logger=custom_logger)
17
18# All logging will now use the custom logger
19log_info("This is using our custom logger!")
20
21agent = Agent()
22agent.print_response("What is 2+2?")

Logging to a File

You can configure Kern to log to a file instead of the console:

1import logging
2from pathlib import Path
3
4from kern.agent import Agent
5from kern.utils.log import configure_agno_logging, log_info
6
7# Create a custom logger that writes to a file
8custom_logger = logging.getLogger("file_logger")
9
10# Ensure tmp directory exists
11log_file_path = Path("tmp/log.txt")
12log_file_path.parent.mkdir(parents=True, exist_ok=True)
13
14# Use FileHandler to write to file
15handler = logging.FileHandler(log_file_path)
16formatter = logging.Formatter("%(levelname)s: %(message)s")
17handler.setFormatter(formatter)
18custom_logger.addHandler(handler)
19custom_logger.setLevel(logging.INFO)
20custom_logger.propagate = False
21
22# Configure Kern to use the file logger
23configure_agno_logging(custom_default_logger=custom_logger)
24
25# All logs will be written to tmp/log.txt
26log_info("This is using our file logger!")
27
28agent = Agent()
29agent.print_response("Tell me a fun fact")

Multiple Loggers

You can configure different loggers for your Agents, Teams and Workflows:

1import logging
2
3from kern.agent import Agent
4from kern.team import Team
5from kern.workflow import Workflow
6from kern.workflow.step import Step
7from kern.utils.log import configure_agno_logging, log_info
8
9# Create custom loggers for different components
10custom_agent_logger = logging.getLogger("agent_logger")
11custom_team_logger = logging.getLogger("team_logger")
12custom_workflow_logger = logging.getLogger("workflow_logger")
13
14# Configure handlers and formatters for each
15for logger in [custom_agent_logger, custom_team_logger, custom_workflow_logger]:
16 handler = logging.StreamHandler()
17 handler.setFormatter(logging.Formatter("[%(name)s] %(levelname)s: %(message)s"))
18 logger.addHandler(handler)
19 logger.setLevel(logging.INFO)
20 logger.propagate = False
21
22# Workflow logs at DEBUG level when debug_mode is enabled
23# Set workflow logger to DEBUG to see these logs
24custom_workflow_logger.setLevel(logging.DEBUG)
25
26# Apply the configuration
27configure_agno_logging(
28 custom_default_logger=custom_agent_logger,
29 custom_agent_logger=custom_agent_logger,
30 custom_team_logger=custom_team_logger,
31 custom_workflow_logger=custom_workflow_logger,
32)
33
34# All logging will now use the custom agent logger by default
35log_info("Using custom loggers!")
36
37# Create agent and team
38agent = Agent()
39team = Team(members=[agent])
40
41# Agent will use custom_agent_logger
42agent.print_response("What is 2+2?")
43
44# Team will use custom_team_logger
45team.print_response("Tell me a short joke")
46
47# Workflow will use custom_workflow_logger
48workflow = Workflow(
49 debug_mode=True,
50 steps=[Step(name="step1", agent=agent)]
51)
52workflow.print_response("Tell me a fun fact")

Using Named Loggers

As it's conventional in Python, you can also provide custom loggers just by setting loggers with specific names. This is useful if you want to set them up using configuration files.

Kern automatically recognizes and uses these logger names:

  • kern will be used for all Agent logs
  • kern-team will be used for all Team logs
  • kern-workflow will be used for all Workflow logs
1import logging
2from kern.agent import Agent
3from kern.team import Team
4from kern.workflow import Workflow
5from kern.workflow.step import Step
6
7# Set up named loggers BEFORE creating agents/teams/workflows
8logger_configs = [
9 ("kern", "agent.log"),
10 ("kern-team", "team.log"),
11 ("kern-workflow", "workflow.log"),
12]
13
14for logger_name, log_file in logger_configs:
15 logger = logging.getLogger(logger_name)
16 logger.setLevel(logging.INFO)
17 handler = logging.FileHandler(log_file)
18 handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
19 logger.addHandler(handler)
20 logger.propagate = False
21
22# Kern will automatically detect and use these loggers
23agent = Agent()
24agent.print_response("Hello from agent!") # Agent logs will go to agent.log
25
26team = Team(members=[agent])
27team.print_response("Hello from team!") # Team logs will go to team.log
28
29# Workflow requires debug mode to use the workflow logger
30workflow = Workflow(
31 debug_mode=True,
32 steps=[Step(name="step1", agent=agent)]
33)
34workflow.run("Hello from workflow!") # Workflow logs will go to workflow.log

Learn more