@@ -35,7 +35,8 @@ defmodule Condukt.Session do
3535 SessionID ,
3636 SessionStore ,
3737 Telemetry ,
38- Tool
38+ Tool ,
39+ TraceContext
3940 }
4041
4142 alias Condukt.MCP
@@ -58,9 +59,7 @@ defmodule Condukt.Session do
5859 :pid ,
5960 :agent_module ,
6061 :runtime ,
61- :model ,
62- :thinking_level ,
63- :max_tokens ,
62+ :llm ,
6463 :configured_system_prompt ,
6564 :system_prompt ,
6665 :tools ,
@@ -71,8 +70,6 @@ defmodule Condukt.Session do
7170 :secrets ,
7271 :mcp_registry ,
7372 :notifier ,
74- :api_key ,
75- :base_url ,
7673 :session_store ,
7774 :session_store_opts ,
7875 :compactor ,
@@ -126,6 +123,7 @@ defmodule Condukt.Session do
126123 |> Keyword . put ( :explicit_keys , explicit_keys )
127124 |> put_configured_opt ( config , :api_key )
128125 |> put_configured_opt ( config , :base_url )
126+ |> put_configured_opt ( config , :llm_request_options , fn -> [ ] end )
129127 |> put_configured_opt ( config , :runtime , fn -> agent_runtime ( agent_module ) end )
130128 |> put_configured_opt ( config , :model , fn -> agent_module . model ( ) end )
131129 |> put_configured_opt ( config , :thinking_level , fn -> agent_module . thinking_level ( ) end )
@@ -209,7 +207,7 @@ defmodule Condukt.Session do
209207 """
210208 def run ( agent , prompt , opts \\ [ ] ) do
211209 timeout = opts [ :timeout ] || @ default_timeout
212- call_session ( agent , { :run , prompt , opts } , timeout )
210+ call_session ( agent , { :run , prompt , attach_trace_context ( opts ) } , timeout )
213211 end
214212
215213 defp call_session ( agent , request , timeout ) do
@@ -263,7 +261,7 @@ defmodule Condukt.Session do
263261 fn ->
264262 ref = make_ref ( )
265263 :ok = GenServer . call ( agent , { :subscribe , self ( ) , ref } )
266- :ok = GenServer . cast ( agent , { :stream , prompt , opts , ref } )
264+ :ok = GenServer . cast ( agent , { :stream , prompt , attach_trace_context ( opts ) , ref } )
267265 ref
268266 end ,
269267 fn ref ->
@@ -381,9 +379,14 @@ defmodule Condukt.Session do
381379 pid: self ( ) ,
382380 agent_module: agent_module ,
383381 runtime: runtime ,
384- model: restore_value ( opts , :model , snapshot && snapshot . model ) ,
385- thinking_level: restore_value ( opts , :thinking_level , snapshot && snapshot . thinking_level ) ,
386- max_tokens: Keyword . get ( opts , :max_tokens ) ,
382+ llm: % {
383+ model: restore_value ( opts , :model , snapshot && snapshot . model ) ,
384+ thinking_level: restore_value ( opts , :thinking_level , snapshot && snapshot . thinking_level ) ,
385+ max_tokens: Keyword . get ( opts , :max_tokens ) ,
386+ api_key: opts [ :api_key ] ,
387+ base_url: opts [ :base_url ] ,
388+ request_options: opts [ :llm_request_options ]
389+ } ,
387390 configured_system_prompt: configured_system_prompt ,
388391 system_prompt: Context . compose_system_prompt ( configured_system_prompt , project_context . prompt ) ,
389392 tools: maybe_inject_subagent_tool ( tools , subagents ) ,
@@ -393,8 +396,6 @@ defmodule Condukt.Session do
393396 sandbox: sandbox ,
394397 secrets: secrets ,
395398 mcp_registry: mcp_registry ,
396- api_key: opts [ :api_key ] ,
397- base_url: opts [ :base_url ] ,
398399 session_store: session_store ,
399400 session_store_opts: session_store_opts ( opts ) ,
400401 compactor: opts [ :compactor ] ,
@@ -515,8 +516,10 @@ defmodule Condukt.Session do
515516 else
516517 state = % { state | turn: Turn . start ( state . turn ) }
517518 parent = self ( )
519+ trace_context = TraceContext . capture ( opts )
518520
519521 Task . start ( fn ->
522+ TraceContext . attach ( trace_context )
520523 result = do_run ( state , prompt , opts )
521524 GenServer . cast ( parent , { :run_complete , from , result } )
522525 end )
@@ -693,6 +696,7 @@ defmodule Condukt.Session do
693696 system_prompt: state . system_prompt ,
694697 project_context: state . project_context ,
695698 runtime_opts: runtime_opts ,
699+ trace_context: TraceContext . current ( ) ,
696700 assigns: state . assigns ,
697701 user_state: state . user_state
698702 }
@@ -745,7 +749,6 @@ defmodule Condukt.Session do
745749 defp agent_loop ( state , messages , max_turns , turn ) do
746750 context = Translate . context ( messages , outbound_redactor ( state ) , state . system_prompt )
747751 tools = build_req_llm_tools ( state . tools , state )
748- llm_opts = Translate . llm_opts ( llm_config ( state ) , tools )
749752
750753 result =
751754 Telemetry . span (
@@ -755,7 +758,7 @@ defmodule Condukt.Session do
755758 Retry . with_retry (
756759 state . retry ,
757760 fn -> false end ,
758- fn -> ReqLLM . generate_text ( state . model , context , llm_opts ) end
761+ fn -> ReqLLM . generate_text ( state . llm . model , context , llm_opts ( state , tools ) ) end
759762 )
760763 end ,
761764 & llm_turn_stop_metadata / 1
@@ -798,8 +801,11 @@ defmodule Condukt.Session do
798801 defp start_stream_task ( state , prompt , opts , subscriber_ref ) do
799802 parent = self ( )
800803 abort_ref = state . turn . abort_ref
804+ trace_context = TraceContext . capture ( opts )
801805
802806 Task . start ( fn ->
807+ TraceContext . attach ( trace_context )
808+
803809 result =
804810 do_stream (
805811 state ,
@@ -820,7 +826,6 @@ defmodule Condukt.Session do
820826 defp stream_turn ( state , messages , max_turns , turn , emit , abort_ref ) do
821827 context = Translate . context ( messages , outbound_redactor ( state ) , state . system_prompt )
822828 tools = build_req_llm_tools ( state . tools , state )
823- llm_opts = Translate . llm_opts ( llm_config ( state ) , tools )
824829
825830 emitted_counter = :counters . new ( 1 , [ :atomics ] )
826831 emitted? = fn -> :counters . get ( emitted_counter , 1 ) > 0 end
@@ -830,7 +835,7 @@ defmodule Condukt.Session do
830835 emit . ( event )
831836 end
832837
833- attempt = fn -> run_stream_attempt ( state . model , context , llm_opts , tracked_emit ) end
838+ attempt = fn -> run_stream_attempt ( state . llm . model , context , llm_opts ( state , tools ) , tracked_emit ) end
834839
835840 result =
836841 Telemetry . span (
@@ -899,13 +904,30 @@ defmodule Condukt.Session do
899904
900905 defp llm_config ( state ) do
901906 [
902- api_key: state . api_key ,
903- base_url: state . base_url ,
904- thinking_level: state . thinking_level ,
905- max_tokens: state . max_tokens
907+ api_key: state . llm . api_key ,
908+ base_url: state . llm . base_url ,
909+ thinking_level: state . llm . thinking_level ,
910+ max_tokens: state . llm . max_tokens ,
911+ request_options: state . llm . request_options
906912 ]
907913 end
908914
915+ defp llm_opts ( state , tools ) do
916+ trace_headers =
917+ TraceContext . current ( )
918+ |> TraceContext . child ( )
919+ |> TraceContext . headers ( state . id )
920+
921+ Translate . llm_opts ( llm_config ( state ) , tools , trace_headers )
922+ end
923+
924+ defp attach_trace_context ( opts ) do
925+ case TraceContext . capture ( opts ) do
926+ nil -> Keyword . delete ( opts , :trace_context )
927+ context -> Keyword . put ( opts , :trace_context , context )
928+ end
929+ end
930+
909931 defp build_req_llm_tools ( tools , state ) do
910932 Enum . map ( tools , fn tool_spec ->
911933 spec = Tool . to_spec ( tool_spec )
@@ -936,13 +958,17 @@ defmodule Condukt.Session do
936958 defp execute_tool_calls ( state , assistant_message , messages , emit \\ & noop_emit / 1 ) do
937959 tool_calls = Message . tool_calls ( assistant_message )
938960 tool_map = build_tool_map ( state . tools )
961+ trace_context = TraceContext . current ( )
939962
940963 Enum . each ( tool_calls , fn { id , name , args } -> emit . ( { :tool_call , name , id , args } ) end )
941964
942965 { tool_results , assigns_diff } =
943966 tool_calls
944967 |> Task . async_stream (
945- fn tool_call -> execute_tool_call ( tool_map , tool_call , state ) end ,
968+ fn tool_call ->
969+ TraceContext . attach ( trace_context )
970+ execute_tool_call ( tool_map , tool_call , state )
971+ end ,
946972 ordered: true ,
947973 timeout: tool_timeout ( state )
948974 )
@@ -975,7 +1001,6 @@ defmodule Condukt.Session do
9751001 metadata = % {
9761002 tool: name ,
9771003 tool_call_id: id ,
978- args: args ,
9791004 session_id: state . id ,
9801005 agent: state . agent_module
9811006 }
@@ -988,33 +1013,32 @@ defmodule Condukt.Session do
9881013 )
9891014 end
9901015
991- defp tool_call_stop_metadata ( { % Message { content: { :error , _ } = error } , _assigns } ) , do: % { status: :error , result: error }
1016+ defp tool_call_stop_metadata ( { % Message { content: { :error , _error } } , _assigns } ) , do: % { status: :error }
9921017
993- defp tool_call_stop_metadata ( { % Message { content: content } , _assigns } ) , do: % { status: :ok , result: content }
1018+ defp tool_call_stop_metadata ( { % Message { } , _assigns } ) , do: % { status: :ok }
9941019
9951020 defp llm_turn_metadata ( state , messages , turn , streaming? ) do
9961021 % {
9971022 agent: state . agent_module ,
9981023 session_id: state . id ,
999- model: Translate . model_identifier ( state . model ) ,
1024+ model: Translate . model_identifier ( state . llm . model ) ,
10001025 turn: turn ,
10011026 streaming?: streaming? ,
1002- messages: messages ,
1027+ message_count: length ( messages ) ,
10031028 tool_count: length ( state . tools )
10041029 }
10051030 end
10061031
10071032 defp llm_turn_stop_metadata ( { :ok , response } ) do
10081033 % {
10091034 status: :ok ,
1010- assistant_message: Translate . response_to_message ( response ) ,
10111035 usage: Map . get ( response , :usage ) ,
10121036 finish_reason: Map . get ( response , :finish_reason )
10131037 }
10141038 end
10151039
10161040 defp llm_turn_stop_metadata ( { :error , reason } ) do
1017- % { status: :error , error: reason }
1041+ % { status: :error , error: Telemetry . error_name ( reason ) }
10181042 end
10191043
10201044 defp task_result_to_tool_result ( { { :ok , { message , assigns } } , _tool_call } ) , do: { message , assigns }
@@ -1084,11 +1108,13 @@ defmodule Condukt.Session do
10841108 secrets: state . secrets ,
10851109 subagents: state . subagents ,
10861110 subagent_supervisor: state . subagent_supervisor ,
1087- model: state . model ,
1088- thinking_level: state . thinking_level ,
1089- max_tokens: state . max_tokens ,
1090- api_key: state . api_key ,
1091- base_url: state . base_url ,
1111+ model: state . llm . model ,
1112+ thinking_level: state . llm . thinking_level ,
1113+ max_tokens: state . llm . max_tokens ,
1114+ api_key: state . llm . api_key ,
1115+ base_url: state . llm . base_url ,
1116+ llm_request_options: state . llm . request_options ,
1117+ trace_context: TraceContext . current ( ) ,
10921118 assigns: state . assigns
10931119 }
10941120 end
@@ -1212,8 +1238,8 @@ defmodule Condukt.Session do
12121238 id: state . id ,
12131239 actor: state . actor ,
12141240 messages: state . messages ,
1215- model: state . model ,
1216- thinking_level: state . thinking_level ,
1241+ model: state . llm . model ,
1242+ thinking_level: state . llm . thinking_level ,
12171243 system_prompt: state . configured_system_prompt ,
12181244 created_at: state . created_at
12191245 } )
0 commit comments