MCPcopy Index your code
hub / github.com/docker/docker-agent / RunSkillFork

Method RunSkillFork

pkg/runtime/skill_runner.go:32–119  ·  view source on GitHub ↗

RunSkillFork executes a `context: fork` skill as an isolated sub-session. The expanded SKILL.md body becomes the child's first user message; the agent's own system prompt is preserved. Shared by the run_skill tool and the App's slash-command path.

(ctx context.Context, sess *session.Session, args skills.RunSkillArgs, evts EventSink)

Source from the content-addressed store, hash-verified

30// agent's own system prompt is preserved. Shared by the run_skill tool
31// and the App's slash-command path.
32func (r *LocalRuntime) RunSkillFork(ctx context.Context, sess *session.Session, args skills.RunSkillArgs, evts EventSink) (*tools.ToolCallResult, error) {
33 st := r.CurrentAgentSkillsToolset()
34 if st == nil {
35 return tools.ResultError("no skills are available for the current agent"), nil
36 }
37
38 prepared, errResult := st.PrepareForkSubSession(ctx, args)
39 if errResult != nil {
40 return errResult, nil
41 }
42
43 ca := r.currentAgentName()
44
45 // Open the span before any pre-delegation work so model resolution
46 // (inside WithAgentModel) is recorded under runtime.run_skill rather
47 // than the parent session span.
48 //
49 // Skills are workflow-shaped (a coordinated process the agent
50 // orchestrates), so the GenAI semconv `invoke_workflow` operation
51 // applies. Emit it via gen_ai.* attrs alongside the legacy keys
52 // for back-compat.
53 skillAttrs := []attribute.KeyValue{
54 attribute.String(genai.AttrOperationName, genai.OperationInvokeWorkflow),
55 attribute.String(genai.AttrWorkflowName, prepared.SkillName),
56 attribute.String(genai.AttrAgentNameRuntime, ca),
57 attribute.String(genai.AttrConversationID, sess.ID),
58 }
59 if genai.EmitLegacyAttributes() {
60 skillAttrs = append(skillAttrs,
61 attribute.String("agent", ca),
62 attribute.String("skill", prepared.SkillName),
63 attribute.String("session.id", sess.ID),
64 )
65 }
66 // Span name follows the GenAI agent semconv pattern
67 // `invoke_workflow {workflow.name}` so spec-aware backends
68 // classify the span as a workflow invocation. SpanKindInternal is
69 // passed explicitly per spec rather than relying on the SDK
70 // default — keeps intent clear and immune to default changes.
71 spanName := genai.OperationInvokeWorkflow
72 if prepared.SkillName != "" {
73 spanName = genai.OperationInvokeWorkflow + " " + prepared.SkillName
74 }
75 ctx, span := r.startSpan(ctx, spanName,
76 trace.WithSpanKind(trace.SpanKindInternal),
77 trace.WithAttributes(skillAttrs...),
78 )
79 defer span.End()
80
81 slog.DebugContext(ctx, "Running skill as sub-agent",
82 "agent", ca,
83 "skill", prepared.SkillName,
84 "task", prepared.Task,
85 )
86
87 // Apply the skill's optional model override for the sub-session.
88 // On failure we log and fall back to the agent's current model;
89 // restore is CAS-safe and always non-nil.

Callers 1

handleRunSkillMethod · 0.95

Calls 13

currentAgentNameMethod · 0.95
startSpanMethod · 0.95
WithAgentModelMethod · 0.95
runForwardingMethod · 0.95
ResultErrorFunction · 0.92
EmitLegacyAttributesFunction · 0.92
BuildSkillSystemMessageFunction · 0.92
BuildSkillUserMessageFunction · 0.92
PrepareForkSubSessionMethod · 0.80
AttachedFilesSnapshotMethod · 0.80
StringMethod · 0.45

Tested by

no test coverage detected