Skip to content

feat(sdk): runtime skills and context-file management (#36)#37

Merged
ezynda3 merged 3 commits into
masterfrom
feat/36-runtime-skills-context
May 29, 2026
Merged

feat(sdk): runtime skills and context-file management (#36)#37
ezynda3 merged 3 commits into
masterfrom
feat/36-runtime-skills-context

Conversation

@ezynda3

@ezynda3 ezynda3 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Description

Adds a public Go SDK surface for runtime mutation of skills and AGENTS.md-style
context files
. Today, pkg/kit auto-discovers skills and context files during
kit.New() and bakes them into the system prompt — there is no way to change
that set without restarting the Kit instance. This blocks multi-tenant hosts
(chatbots, per-user agents, web services) from swapping per-user instructions
on the fly, which is exactly the scenario the requester describes in #36.

The new methods on *kit.Kit are:

Skills Context files
AddSkill(*Skill) error AddContextFile(*ContextFile) error
LoadAndAddSkill(path) (*Skill, error) LoadAndAddContextFile(path) (*ContextFile, error)
RemoveSkill(name) bool AddContextFileContent(path, content) (*ContextFile, error)
SetSkills([]*Skill) error RemoveContextFile(path) bool
GetSkills() []*Skill SetContextFiles([]*ContextFile) error
GetContextFiles() []*ContextFile

Plus RefreshSystemPrompt() for callers that mutate state through other paths.

Every mutator validates input, takes a per-instance sync.RWMutex, then
recomposes the system prompt from the captured base prompt + current skills +
current context files and pushes the result onto the underlying agent via a
new agent.SetSystemPromptrebuildFantasyAgent path (same mechanism
SetModel already uses). The next LLM call sees the updated prompt; no
restart, no file shuffling.

// Per-user state, applied at request time:
host.AddSkill(&kit.Skill{
    Name:        "polite-french",
    Description: "Respond in French and always greet the user.",
    Content:     "Always reply in French. Open every response with 'Bonjour'.",
})
host.AddContextFileContent(
    fmt.Sprintf("session://%s/AGENTS.md", userID),
    rulesFromDB,
)
// ...later, on logout:
host.RemoveSkill("polite-french")
host.RemoveContextFile(fmt.Sprintf("session://%s/AGENTS.md", userID))

Fixes #36

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactor / cleanup

Design Notes

  • Dedup keys. Skills dedupe by Name, context files dedupe by Path.
    Re-adding the same key replaces in place instead of appending a duplicate,
    matching how SDK consumers would expect upsert to work.
  • Opaque path. ContextFile.Path is not required to be a real
    filesystem path — it's used purely for dedup and for the
    Instructions from: <Path> header injected into the prompt. URIs like
    session://user-123/AGENTS.md work fine, which is what the per-tenant
    use case needs.
  • Base prompt capture. New() now captures the fully-resolved base
    prompt (after --system-prompt file resolution + per-model override
    lookup) onto the Kit struct. Runtime recomposition reuses this captured
    base so model-specific prompts and file paths keep working after mutation.
  • Concurrency. All mutators and readers take the new runtimeMu lock;
    GetSkills / GetContextFiles return defensive snapshot copies so
    callers can iterate without holding the lock. Verified clean under
    go test -race with an 8-goroutine × 50-iteration stress test.
  • Init-time options unchanged. Options.Skills, Options.SkillsDir,
    Options.NoSkills, and Options.NoContextFiles still control the
    starting set; the runtime API mutates from whatever state New()
    produced. No backwards-incompatible change.

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas (godoc on every new exported symbol)
  • I have made corresponding changes to the documentation (pkg/kit/README.md, root README.md, www/pages/sdk/overview.md, www/pages/sdk/options.md)
  • My changes generate no new warnings (go vet, golangci-lint run both clean)
  • I have added tests that prove my fix is effective or that my feature works (pkg/kit/runtime_skills_context_test.go — 13 cases incl. race-stress)
  • New and existing unit tests pass locally with my changes (go test ./... -race)

Files Changed

Code

  • internal/agent/agent.goSetSystemPrompt / GetSystemPrompt on the internal agent (rebuilds the fantasy agent so the next call uses the new prompt).
  • pkg/kit/kit.goruntimeMu, basePrompt capture during New, thread-safe GetSkills / GetContextFiles, composeSystemPrompt snapshots under read lock.
  • pkg/kit/skills.goAddSkill, LoadAndAddSkill, RemoveSkill, SetSkills, applyComposedSystemPrompt, RefreshSystemPrompt; ReloadSkills now hot-applies the recomposed prompt.
  • pkg/kit/context_files.go (new)AddContextFile, AddContextFileContent, LoadAndAddContextFile, RemoveContextFile, SetContextFiles.

Tests

  • pkg/kit/runtime_skills_context_test.go (new) — add/remove/set/replace semantics, validation errors, on-disk loading round-trips, prompt composition verification, 8-goroutine race-stress sweep.

Docs

  • pkg/kit/README.md — new "Runtime Skills and Context Files" section + Key Methods entries.
  • README.md (root) — new "Runtime Skills & Context Files" subsection in the Go SDK area with a cross-link to the docs site.
  • www/pages/sdk/overview.md — full "Runtime skills and context files" section (after In-process MCP servers) covering dedup, opaque paths, thread safety, and interplay with init-time options.
  • www/pages/sdk/options.md — callout under Skills & configuration cross-referencing the runtime API.

Backwards Compatibility

Fully additive. Existing callers see no behavioural change:

  • Options.Skills / SkillsDir / NoSkills / NoContextFiles still control the startup set.
  • composeSystemPrompt produces the same output it did before whenever no runtime mutations have happened.
  • The only signature changes are the new exported methods on *kit.Kit; nothing was removed or renamed.

Summary by CodeRabbit

  • New Features

    • Add/remove/replace skills and AGENTS.md-style context files at runtime (including per-session content), with dynamic system-prompt refresh and thread-safe concurrent operations
    • Snapshot-style getters returning safe copies of active skills/context
  • Documentation

    • New “Runtime Skills & Context Files” guides and SDK overview updates describing behavior and deduplication semantics
  • Tests

    • Extensive tests for runtime mutations, composition, deduplication, loading, and concurrency safety

Review Change Stack

Let SDK consumers add, remove, and replace skills and AGENTS.md-style
context files after Kit construction. Every mutation recomposes the
system prompt and applies it to the agent so the next turn picks up
the new instructions without restarting Kit.

- AddSkill / LoadAndAddSkill / RemoveSkill / SetSkills on *kit.Kit
- AddContextFile / AddContextFileContent / LoadAndAddContextFile /
  RemoveContextFile / SetContextFiles on *kit.Kit
- RefreshSystemPrompt to force a manual recomposition
- agent.SetSystemPrompt / GetSystemPrompt on the internal agent so
  the composed prompt rebuilds the fantasy agent on the next call
- Per-instance runtimeMu guards skills/contextFiles; GetSkills and
  GetContextFiles return defensive snapshots safe for concurrent use
- Capture the resolved basePrompt during New so recomposition keeps
  per-model overrides and --system-prompt file resolution intact
- Skills dedupe by Name; context files dedupe by Path (opaque ID,
  not required to be a real filesystem path)

Tests cover add/remove/set/replace semantics, validation errors,
disk loading round-trips, prompt composition, and an 8-goroutine
race-stress sweep (go test -race clean).

Docs: pkg/kit/README, root README Go SDK section, www sdk/overview
"Runtime skills and context files" section, www sdk/options callout
cross-referencing the new API.

Fixes #36
@mark-iii-labs-huly

Copy link
Copy Markdown

Connected to Huly®: KIT-38

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 813df08a-23fa-4bc2-be83-d3c2cd39662b

📥 Commits

Reviewing files that changed from the base of the PR and between ce1d7af and 58b8aa0.

📒 Files selected for processing (2)
  • internal/agent/agent.go
  • pkg/kit/runtime_skills_context_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/kit/runtime_skills_context_test.go

📝 Walkthrough

Walkthrough

Adds thread-safe runtime APIs to Kit for adding/removing/replacing skills and AGENTS.md-like context files, captures the base prompt at New(), composes and applies a recomposed system prompt on mutations, exposes agent-level Set/GetSystemPrompt, includes tests (including race checks), and updates documentation.

Changes

Runtime Mutation of Skills and Context Files

Layer / File(s) Summary
Foundation: Concurrency safeguards and prompt composition
pkg/kit/kit.go
Adds basePrompt captured during New(), introduces runtimeMu RWMutex protecting contextFiles and skills, updates composeSystemPrompt to snapshot state under RLock, and provides snapshot-returning GetContextFiles/GetSkills and RLock-protected expandSkillCommand.
Agent-level system prompt control
internal/agent/agent.go
Adds promptMu, SetSystemPrompt(prompt string) (mutates stored prompt and rebuilds fantasy agent), and GetSystemPrompt() string (reads stored prompt) with mutex protection.
Runtime skills mutation API
pkg/kit/skills.go
Implements AddSkill, LoadAndAddSkill, RemoveSkill, SetSkills with name-based deduplication and validation; updates m.skills under runtimeMu, clears skill cache, and re-applies composed system prompt. Adds applyComposedSystemPrompt() and RefreshSystemPrompt().
Runtime context files mutation API
pkg/kit/context_files.go
Implements AddContextFile, AddContextFileContent, LoadAndAddContextFile, RemoveContextFile, SetContextFiles with path-based deduplication, input validation, defensive copies, absolute-path normalization for disk loads, and prompt recomposition on mutation.
Test coverage for runtime mutations and concurrency
pkg/kit/runtime_skills_context_test.go
Adds tests for skill/context add/remove/replace/load, validation semantics, composition correctness, and a concurrency stress test exercising thread-safety under go test -race.
Documentation and API reference updates
README.md, pkg/kit/README.md, www/pages/sdk/*
Adds runtime skills & context-files documentation and usage examples; updates pkg/kit API reference and notes that init-time options only affect initial state.

Sequence Diagram(s)

sequenceDiagram
  participant SDK_User
  participant Kit
  participant runtimeMu
  participant composeSystemPrompt
  participant Agent
  SDK_User->>Kit: AddSkill(newSkill)
  Kit->>runtimeMu: Lock (write)
  runtimeMu-->>Kit: locked
  Kit->>Kit: Validate, deduplicate by name
  Kit->>Kit: Update skills slice
  Kit->>runtimeMu: Unlock
  Kit->>composeSystemPrompt: Recompose prompt from base + snapshots
  composeSystemPrompt->>runtimeMu: RLock
  runtimeMu-->>composeSystemPrompt: locked
  composeSystemPrompt->>composeSystemPrompt: Snapshot contextFiles & skills
  composeSystemPrompt-->>Kit: Composed prompt with new skill
  composeSystemPrompt->>runtimeMu: RUnlock
  Kit->>Agent: SetSystemPrompt(composed)
  Agent-->>Kit: Rebuilt with new prompt
  Kit-->>SDK_User: Success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A toolkit now learns to evolve and grow,
Skills spring forth and context flows free.
Per-session files find their proper place,
Mutex guards the dance, prompts recompose with grace—
Rabbit hops on; the host says, “Ready!” 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately captures the primary feature: runtime management of skills and context files for the SDK.
Linked Issues check ✅ Passed PR fully implements the requested API for dynamic skill/context file management with add/remove/set methods, input validation, session-scoped paths, and runtime application without restart.
Out of Scope Changes check ✅ Passed All changes are directly aligned with runtime skill/context file management objectives; documentation, test coverage, and agent synchronization are necessary supporting implementations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/36-runtime-skills-context

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/kit/skills.go (1)

184-195: ⚡ Quick win

Skill mutators store the caller's pointer; context-file mutators defensively copy.

AddContextFile deliberately copies the input (stored := &ContextFile{...}) so "later mutations by the caller don't race with the agent reading the composed prompt." AddSkill stores the caller's *skill directly, so a caller that retains and later mutates the passed Skill races with composeSystemPrompt reading Name/Description/ContentruntimeMu only guards the slice, not the pointee. SetSkills (Line 253-254) has the same gap (copy only duplicates pointers).

♻️ Mirror the context-file defensive copy
+	// Defensive copy so later caller-side mutations don't race with the agent
+	// reading the composed prompt (mirrors AddContextFile).
+	stored := *skill
+
 	m.runtimeMu.Lock()
 	replaced := false
 	for i, s := range m.skills {
 		if s.Name == skill.Name {
-			m.skills[i] = skill
+			m.skills[i] = &stored
 			replaced = true
 			break
 		}
 	}
 	if !replaced {
-		m.skills = append(m.skills, skill)
+		m.skills = append(m.skills, &stored)
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/kit/skills.go` around lines 184 - 195, AddSkill (and similarly SetSkills)
stores the caller's *Skill directly into m.skills which lets external code
mutate the pointee after the mutex is released and race with
composeSystemPrompt; instead, create a defensive copy of the Skill data
(allocate a new Skill value and copy Name, Description, Content, and any
slice/map fields deeply as needed) and store the new pointer in m.skills (and
when replacing in the loop that checks s.Name). Ensure SetSkills copies each
incoming *Skill into fresh allocations too so runtimeMu continues to only guard
the slice, not the caller-owned pointees accessed by composeSystemPrompt.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/kit/skills.go`:
- Around line 269-278: applyComposedSystemPrompt currently releases runtimeMu
before calling m.agent.SetSystemPrompt, causing races because
Agent.SetSystemPrompt/rebuildFantasyAgent lack synchronization; either make
Agent.SetSystemPrompt thread-safe by adding internal locking around
a.systemPrompt and rebuildFantasyAgent (preferable) or keep Kit.runtimeMu held
(use write lock) across composeSystemPrompt and m.agent.SetSystemPrompt to
serialize updates; update tests to instantiate a non-nil Agent and run the
concurrent mutation stress test under -race to verify the fix.

---

Nitpick comments:
In `@pkg/kit/skills.go`:
- Around line 184-195: AddSkill (and similarly SetSkills) stores the caller's
*Skill directly into m.skills which lets external code mutate the pointee after
the mutex is released and race with composeSystemPrompt; instead, create a
defensive copy of the Skill data (allocate a new Skill value and copy Name,
Description, Content, and any slice/map fields deeply as needed) and store the
new pointer in m.skills (and when replacing in the loop that checks s.Name).
Ensure SetSkills copies each incoming *Skill into fresh allocations too so
runtimeMu continues to only guard the slice, not the caller-owned pointees
accessed by composeSystemPrompt.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f94b09a6-66a4-4902-b065-81c830b5638f

📥 Commits

Reviewing files that changed from the base of the PR and between 1a2f6da and ce1d7af.

📒 Files selected for processing (9)
  • README.md
  • internal/agent/agent.go
  • pkg/kit/README.md
  • pkg/kit/context_files.go
  • pkg/kit/kit.go
  • pkg/kit/runtime_skills_context_test.go
  • pkg/kit/skills.go
  • www/pages/sdk/options.md
  • www/pages/sdk/overview.md

Comment thread pkg/kit/skills.go
ezynda3 added 2 commits May 29, 2026 18:00
- add promptMu to Agent guarding systemPrompt writes and the fantasy
  agent rebuild, fixing a data race when Kit.applyComposedSystemPrompt
  is invoked concurrently
- read systemPrompt under the same lock in GetSystemPrompt
- update the thread-safety stress test to use a non-nil agent so the
  SetSystemPrompt path is actually exercised under -race
@ezynda3 ezynda3 merged commit ab2a77c into master May 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: SDK for Skills And Context add method to load from aplication

1 participant