Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import logging
import logging.handlers
import os
import tempfile
from urllib.parse import urlsplit, urlunsplit

try:
Expand Down Expand Up @@ -35,51 +36,55 @@ def load_dotenv(*_a, **_kw):
)

# --- File logging: write detailed turn logs to rotating files ---
_log_dir = os.environ.get("DUPLEX_LOG_DIR", "logs")
os.makedirs(_log_dir, exist_ok=True)
# Hosted agent containers can have a read-only filesystem, so file logging is
# best-effort: fall back to console-only logging when the log directory or a
# handler cannot be created.
_log_dir = os.environ.get("DUPLEX_LOG_DIR") or os.path.join(
tempfile.gettempdir(), "duplex-live-agent-logs"
)

_file_formatter = logging.Formatter(
"%(asctime)s %(name)s %(levelname)s: %(message)s"
)

# Realtime router I/O (user speech, bot replies, tool calls)
_rt_file_handler = logging.handlers.RotatingFileHandler(
os.path.join(_log_dir, "realtime_turns.log"),
maxBytes=10 * 1024 * 1024, # 10 MB
backupCount=5,
encoding="utf-8",
)
_rt_file_handler.setLevel(logging.INFO)
_rt_file_handler.setFormatter(_file_formatter)
_realtime_io_logger = logging.getLogger("duplex_agent.realtime_io")
_realtime_io_logger.addHandler(_rt_file_handler)
_realtime_io_logger.setLevel(logging.INFO)
_file_logging_enabled = False
if _file_logging_enabled:
try:
os.makedirs(_log_dir, exist_ok=True)
except OSError as exc:
_file_logging_enabled = False
logger.warning(
"File logging disabled: cannot create log directory %r (%s)", _log_dir, exc
)

# LLM calls (handoff workflow requests/responses)
_llm_file_handler = logging.handlers.RotatingFileHandler(
os.path.join(_log_dir, "llm_calls.log"),
maxBytes=10 * 1024 * 1024,
backupCount=5,
encoding="utf-8",
)
_llm_file_handler.setLevel(logging.INFO)
_llm_file_handler.setFormatter(_file_formatter)
_llm_calls_logger = logging.getLogger("duplex_agent.llm_calls")
_llm_calls_logger.addHandler(_llm_file_handler)
_llm_calls_logger.setLevel(logging.INFO)

def _add_rotating_file_handler(logger_name: str, filename: str) -> None:
"""Attach a rotating file handler to *logger_name*, tolerating FS errors."""
_target = logging.getLogger(logger_name)
_target.setLevel(logging.INFO)
if not _file_logging_enabled:
return
try:
_handler = logging.handlers.RotatingFileHandler(
os.path.join(_log_dir, filename),
maxBytes=10 * 1024 * 1024, # 10 MB
backupCount=5,
encoding="utf-8",
)
except OSError as exc:
logger.warning("File logging disabled for %s: %s", logger_name, exc)
return
_handler.setLevel(logging.INFO)
_handler.setFormatter(_file_formatter)
_target.addHandler(_handler)


# Realtime router I/O (user speech, bot replies, tool calls)
_add_rotating_file_handler("duplex_agent.realtime_io", "realtime_turns.log")
# LLM calls (handoff workflow requests/responses)
_add_rotating_file_handler("duplex_agent.llm_calls", "llm_calls.log")
# Workflow events
_evt_file_handler = logging.handlers.RotatingFileHandler(
os.path.join(_log_dir, "workflow_events.log"),
maxBytes=10 * 1024 * 1024,
backupCount=5,
encoding="utf-8",
)
_evt_file_handler.setLevel(logging.INFO)
_evt_file_handler.setFormatter(_file_formatter)
_workflow_events_logger = logging.getLogger("duplex_agent.workflow_events")
_workflow_events_logger.addHandler(_evt_file_handler)
_workflow_events_logger.setLevel(logging.INFO)
_add_rotating_file_handler("duplex_agent.workflow_events", "workflow_events.log")

# Enable detailed LLM request/response logging with LOG_LEVEL=DEBUG or:
# DUPLEX_EVENT_LOG_LEVEL=DEBUG to see every workflow event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ azure-identity>=1.20.0
python-dotenv>=1.0.0

# Background agents — MAF
agent-framework
agent-framework-foundry
agent-framework-orchestrations
agent-framework-core==1.10.0
agent-framework-foundry==1.10.0
agent-framework-orchestrations==1.0.0

github-copilot-sdk>=0.2.0
github-copilot-sdk==0.3.0

# debugpy enables local debugging of this agent with the Foundry Toolkit VS Code extension.
debugpy
Loading