agent
| Kind | kit |
|---|---|
| Categories | ai workflow |
| Keywords | agent ai workflow tools memory |
Composable Agent primitives for Kit applications
Files
| File | Description |
|---|---|
.editorconfig | Editor formatting configuration |
.gitignore | Git ignore rules for local package artifacts |
.tool-versions | asdf tool versions |
LICENSE | MIT license file |
README.md | This file |
examples/basic.kit | Basic single-agent example with memory |
examples/workflow.kit | Multi-agent workflow routing example |
kit.toml | Package manifest with metadata and tasks |
src/main.kit | Public Kit.Agent facade and re-exports |
src/app-runner.kit | App and runner facade with immutable stores |
src/artifact-store.kit | Pure immutable artifact store helpers |
src/memory-store.kit | Memory store and memory service adapter boundary |
src/runner.kit | Model adapters, actions, hooks, plugins, and turn runner |
src/session-store.kit | Pure immutable session store helpers |
src/session.kit | Session construction, event appending, and state patching |
src/spec.kit | Agent spec builders and memory helpers |
src/tool.kit | Tool declarations, schema metadata, validation, and dispatch |
src/types.kit | Shared Agent types, events, actions, and result records |
src/workflow.kit | Explicit multi-agent workflow graph runner |
tests/core.test.kit | Core agent, session, tool, runner, and workflow tests |
tests/hooks.test.kit | Runner hook and plugin stack tests |
tests/memory.test.kit | Memory store and service boundary tests |
tests/stores.test.kit | Session and artifact store tests |
tests/tools.test.kit | Tool declaration and argument validation tests |
tests/workflow-invalid-edge.test.kit | Workflow invalid-transfer guard test |
tests/workflow-max-steps.test.kit | Workflow max-step guard test |
tests/workflow-missing-start.test.kit | Workflow missing-start guard test |
tests/workflow-routing.test.kit | Workflow transfer routing test |
Dependencies
No Kit package dependencies.
kit-agent is intentionally provider-neutral and store-neutral. Model
providers, memory backends, vector stores, MCP adapters, telemetry packages, and
database packages should integrate through the package records instead of
becoming dependencies of this core package.
Installation
kit add gitlab.com/kit-lang/packages/kit-agent.gitUsage
import Kit.Agent as Agent
main = fn =>
read-memory = fn(key: String) => if key == "profile:name" then Some "Kit" else None
write-memory = fn(-key: String, -value: String) => Ok no-op
delete-memory = fn(-key: String) => Ok no-op
memory = Agent.memory "profile-memory" read-memory write-memory delete-memory
agent = Agent.define "assistant" "Answer with the user's profile"
|> Agent.with-description "Small local example agent"
|> Agent.with-memory memory
model = Agent.text-model "local-static" (fn(context) =>
name = Agent.recall context.agent.memory "profile:name" ?? "there"
Ok "Hello ${name}; I saw '${context.input}'."
)
result = Agent.run-turn agent (Agent.default-session "demo" "user-1") "status?" model
match result.output
| Some text -> println text
| None -> println "no output"
println "events=${Agent.event-count result.session}"
mainAgent Concepts
Specs
An AgentSpec describes the local agent contract: name, instructions,
description, mode, tools, memory, initial state, and limits. Specs are immutable
records built with helpers such as Agent.define, Agent.with-tool, and
Agent.with-memory.
Events and Sessions
Sessions hold the event stream and current state. Events cover user messages,
agent messages, tool calls, tool results, state deltas, transfers, escalation,
input requests, artifacts, errors, and terminal run events.
Use Agent.default-session, Agent.append-event, and Agent.patch-state for
local session handling. Use src/session-store.kit helpers when a runner needs
to persist session snapshots between turns.
Actions
Model adapters return Result Agent.Action String.
Implemented actions:
Respond {content}: append an agent message and terminal eventCallTool {id, name, args}: append tool call and tool result/error eventsPatchState {changes}: merge state changes into the sessionTransferToAgent {agent}: request workflow routing to another agentEscalateRun {reason}: append an escalation eventRequestUserInput {prompt}: append an input request eventStopAgent: append a terminal event
Use Agent.text-model when a provider only returns text. Use Agent.model
when a provider, planner, or router returns explicit actions.
App Runner
Agent.app and Agent.runner provide an ADK-style facade around the lower-level
runner functions. A turn returns the updated runner so immutable session,
artifact, and memory stores can be threaded into the next turn.
application = Agent.app "support" agent
runner = Agent.runner application
first = Agent.run-app-turn runner "user-1" "hello" model
second = Agent.run-app-turn first.runner "user-1" "again" modelUse Agent.with-app-hooks to attach lifecycle hooks. Use
Agent.with-app-workflow with Agent.run-app-workflow when the app should run
a configured workflow graph.
Runner Hooks and Plugins
Agent.run-turn-with-hooks adds opt-in lifecycle hooks around the local runner:
before = fn(-context) => Ok UseModel
on-event = fn(event) => Ok event
after = fn(-context, result) => Ok result
hooks = Agent.run-hooks
before
on-event
after
result = Agent.run-turn-with-hooks agent session "hello" model hooksbefore-runcan returnUseAction actionto skip the model call, or
UseModel to call the configured model.
on-eventcan transform or reject events before they are appended.after-runcan transform the finalRunResult.
Plugins are named hook bundles. A plugin stack composes hooks in order, giving
integration packages a small lifecycle surface without taking over the runner.
hooks = Agent.run-hooks before on-event after
plugins = Agent.plugin-stack
|> Agent.with-plugin (Agent.plugin "telemetry" hooks)
application = Agent.app "support" agent
|> Agent.with-app-hooks (Agent.plugin-stack-hooks plugins)Use hooks and plugins for local policy checks, telemetry/event shaping, test
doubles, cache lookup, tracing, and package adapters such as kit-otel.
Workflows
Workflows bind agent specs to model adapters and allow explicit transfer edges.
import Kit.Agent.{Respond, TransferToAgent}
router = Agent.define "router" "Route requests to a specialist"
billing = Agent.define "billing" "Handle billing requests"
router-model = Agent.model "router-model" (fn(context) =>
if String.contains? context.input "invoice" then
Ok (TransferToAgent {agent: "billing"})
else
Ok (Respond {content: "router handled ${context.input}"})
)
billing-model = Agent.text-model "billing-model" (fn(context) =>
Ok "billing handled ${context.input}"
)
flow = Agent.workflow "support" "router" [
Agent.runtime router router-model,
Agent.runtime billing billing-model
] |> Agent.with-edge (Agent.edge "router" "billing")The runner rejects transfers that do not have an explicit edge and stops with an
agent error when max-steps is reached.
Tool Integration
Tools keep runtime execution provider-neutral with `Map String String -> Result
String String`, while declarations carry schema metadata for provider and
protocol adapters:
import Kit.Agent.{ToolString}
base-schema = Agent.tool-schema "search" "Search documents"
query-schema = Agent.with-schema-param base-schema (Agent.required-param "query" "Search query" ToolString)
schema = Agent.with-schema-metadata query-schema "provider" "mcp"
search = Agent.tool-from-declaration schema (fn(args) =>
Ok (Map.get args "query" ?? "")
)ToolDeclaration includes parameters, metadata, long-running markers, and
confirmation requirements. Provider packages can translate declarations into
their native tool schemas while runners call Agent.run-tool for validation and
execution.
Useful integration points:
kit-mcpcan expose MCP tools asAgent.Tool.- HTTP/client packages can expose remote tools.
- Model-provider packages can translate tool declarations to provider schemas.
Memory and Stores
The core package exposes a small string key/value memory boundary:
Agent.memory name read write deleteFor richer long-term memory, kit-agent also includes a pure immutable
reference store and a service boundary:
store = Agent.memory-store
write = Agent.put-memory store "app" "user-1" "session-1" "profile:name" "Kit likes agents" "user" None Map.empty
hits = Agent.search-memory write.store "app" "user-1" "agents"
session-write = Agent.add-session-to-memory write.store session Map.emptyMemoryService mirrors the same app/user/session shape for package-backed
adapters: add memory, search scoped memory, and delete memory for a session.
Adapters should live in integration packages or optional modules. Good backend
targets include:
kit-etsfor local concurrent ephemeral memorykit-memcachedfor cache-backed memorykit-redisandkit-hiredisfor Redis-backed memorykit-embeddingsfor retrieval-oriented memory searchkit-sqlite,kit-postgres, andkit-duckdbfor database-backed memory
kit-agent also includes pure immutable session and artifact stores:
sessions = Agent.session-store
created = Agent.create-session sessions "app" "user-1" Map.empty
updated = Agent.append-session-event created.store "app" "user-1" event
artifacts = Agent.artifact-store
write = Agent.put-artifact artifacts "report" "text/plain" "content" Map.empty
latest = Agent.latest-artifact write.store "report"These stores are useful for tests and local workflows. Production adapters can
map the same operations to existing Kit storage packages.
Development
Running Examples
Run examples with the interpreter:
kit run examples/basic.kit
kit run examples/workflow.kitCompile examples to native binaries:
kit build examples/basic.kit -o /tmp/kit-agent-basic --no-spinner
kit build examples/workflow.kit -o /tmp/kit-agent-workflow --no-spinnerRunning Tests
Run the test suite:
kit test tests/Run the test suite with coverage:
kit test tests/ --coverageRunning kit dev
Run the standard development workflow:
kit dev --no-spinnerThis will:
- Check formatting for
src/,examples/, andtests/ - Type-check package sources
- Type-check examples
- Run tests
Generating Documentation
Generate API documentation from doc comments:
kit docNote: Kit sources with doc comments (##) will generate HTML documents in
docs/*.html.
Cleaning Build Artifacts
Remove generated files, caches, and build artifacts:
kit task cleanNote: Defined in kit.toml.
Local Installation
To install this package locally for development:
kit install /Users/ejstembler/Projects/ejs/kit-lang/packages/kit-agentThis installs the package to ~/.kit/packages/@kit/agent/, making it available
for import as Kit.Agent in other projects.
License
This package is released under the MIT License - see LICENSE for
details.
Exported Functions & Types
artifact-store
Create an empty immutable artifact store.
() -> ArtifactStore
artifact
Create an artifact value.
(NonEmptyString, PositiveInt, String, String, Map String String) -> Artifact
list-artifacts
List artifacts matching a key in insertion order.
(ArtifactStore, NonEmptyString) -> List Artifact
latest-artifact
Return the latest artifact for a key, if present.
(ArtifactStore, NonEmptyString) -> Option Artifact
get-artifact
Return a specific artifact version for a key.
(ArtifactStore, NonEmptyString, PositiveInt) -> Option Artifact
put-artifact
Add a new artifact version for a key.
(ArtifactStore, NonEmptyString, String, String, Map String String) -> ArtifactWrite
delete-artifacts
Delete all artifact versions for a key.
(ArtifactStore, NonEmptyString) -> ArtifactStore
tool
Create a tool from a name, description, and handler.
(NonEmptyString, String, Map String String -> Result String String) -> Tool
tool-schema
Create an empty tool declaration.
(NonEmptyString, String) -> ToolDeclaration
tool-param
Create a tool parameter declaration.
(NonEmptyString, String, ToolValueType, Bool) -> ToolParam
required-param
Create a required tool parameter declaration.
(NonEmptyString, String, ToolValueType) -> ToolParam
optional-param
Create an optional tool parameter declaration.
(NonEmptyString, String, ToolValueType) -> ToolParam
tool-value-type-name
Return the stable provider-facing name for a tool value type.
ToolValueType -> String
with-schema-param
Add a parameter to a tool declaration.
(ToolDeclaration, ToolParam) -> ToolDeclaration
with-schema-metadata
Add metadata to a tool declaration.
(ToolDeclaration, NonEmptyString, String) -> ToolDeclaration
with-schema-long-running
Mark a tool declaration as long-running.
ToolDeclaration -> ToolDeclaration
with-schema-confirmation
Mark a tool declaration as requiring confirmation.
ToolDeclaration -> ToolDeclaration
tool-from-declaration
Build a runnable tool from a declaration and handler.
(ToolDeclaration, Map String String -> Result String String) -> Tool
tool-declaration
Return a provider-facing declaration for a runnable tool.
Tool -> ToolDeclaration
tool-declarations
Return provider-facing declarations for a list of tools.
List Tool -> List ToolDeclaration
with-tool
Add a tool to an agent spec.
(Spec, Tool) -> Spec
find-tool
Find a tool by name.
(List Tool, NonEmptyString) -> Option Tool
has-tool?
Return true when an agent has a tool by name.
(Spec, NonEmptyString) -> Bool
tool-call
Create a tool-call event for an agent.
(Spec, NonEmptyString, NonEmptyString, Map String String) -> Event
validate-tool-args
Validate required tool arguments.
(Tool, Map String String) -> Result Unit String
run-tool
Run a tool and convert the result to an event.
(Tool, NonEmptyString, Map String String) -> Event
memory-service
Create a long-term memory service adapter.
(NonEmptyString, MemoryEntry -> Result Unit String, (NonEmptyString, NonEmptyString, String) -> Result MemorySearch String, (NonEmptyString, NonEmptyString, String) -> Result Unit String) -> MemoryService
memory-store
Create an empty immutable memory store.
() -> MemoryStore
memory-entry
Create a memory entry.
(NonEmptyString, NonEmptyString, String, String, String, String, Option NonNegativeInt, Map String String) -> MemoryEntry
add-memory
Add a memory entry to a store.
(MemoryStore, MemoryEntry) -> MemoryWrite
put-memory
Create and add a memory entry in one step.
(MemoryStore, NonEmptyString, NonEmptyString, String, String, String, String, Option NonNegativeInt, Map String String) -> MemoryWrite
list-memories
List all memory entries for an app/user pair.
(MemoryStore, NonEmptyString, NonEmptyString) -> List MemoryEntry
list-session-memories
List all memory entries for an app/user/session tuple.
(MemoryStore, NonEmptyString, NonEmptyString, String) -> List MemoryEntry
delete-memories
Delete all memory entries for an app/user/session tuple.
(MemoryStore, NonEmptyString, NonEmptyString, String) -> MemoryStore
search-memory
Search memory entries for an app/user pair by key, author, or content.
(MemoryStore, NonEmptyString, NonEmptyString, String) -> MemorySearch
add-events-to-memory
Add session events with textual content to memory.
(MemoryStore, Session, List Event, Map String String) -> MemoryBatchWrite
add-session-to-memory
Add all textual events from a session to memory.
(MemoryStore, Session, Map String String) -> MemoryBatchWrite
session-store
Create an empty immutable session store.
() -> SessionStore
session-key
Build a stable session key from app name and user id.
(NonEmptyString, NonEmptyString) -> String
save-session
Save or replace a session in a store.
(SessionStore, Session) -> SessionStore
create-session
Create and save a new session.
(SessionStore, NonEmptyString, NonEmptyString, Map String String) -> SessionWrite
load-session
Load a session by app name and user id.
(SessionStore, NonEmptyString, NonEmptyString) -> Option Session
delete-session
Delete a session by app name and user id.
(SessionStore, NonEmptyString, NonEmptyString) -> SessionStore
has-session?
Return true when the store has a session for the app/user pair.
(SessionStore, NonEmptyString, NonEmptyString) -> Bool
session-keys
Return all session keys in store order.
SessionStore -> List String
append-session-event
Append an event to an existing session, creating the session if needed.
(SessionStore, NonEmptyString, NonEmptyString, Event) -> SessionWrite
mode-name
Convert an agent execution mode to a stable string.
Mode -> String
no-memory
Memory adapter that ignores all reads and writes.
Memory
memory
Create a memory adapter from plain functions.
(NonEmptyString, String -> Option String, (String, String) -> Result Unit String, String -> Result Unit String) -> Memory
recall
Read a value from a memory adapter.
(Memory, String) -> Option String
remember
Write a value to a memory adapter.
(Memory, String, String) -> Result Unit String
forget
Delete a value from a memory adapter.
(Memory, String) -> Result Unit String
define
Create a default chat agent spec.
(NonEmptyString, String) -> Spec
with-description
Return a copy of an agent with a new description.
(Spec, String) -> Spec
with-mode
Return a copy of an agent with a new execution mode.
(Spec, Mode) -> Spec
with-memory
Return a copy of an agent with a new memory adapter.
(Spec, Memory) -> Spec
with-initial-state
Return a copy of an agent with new initial state.
(Spec, Map String String) -> Spec
with-max-turns
Return a copy of an agent with a new max-turn limit.
(Spec, PositiveInt) -> Spec
with-tool-timeout
Return a copy of an agent with a new tool timeout.
(Spec, NonNegativeInt) -> Spec
event-kind
Return the stable symbol kind for an agent event.
Event -> Symbol
is-terminal-event?
Return true when an event ends the current agent turn.
Event -> Bool
session
Create a session with explicit initial state.
(NonEmptyString, NonEmptyString, Map String String) -> Session
default-session
Create a session with empty initial state.
(NonEmptyString, NonEmptyString) -> Session
apply-event
Append an event and apply any state changes carried by it.
(Session, Event) -> Session
apply-events
Append a list of events in order.
(Session, List Event) -> Session
event-count
Count events in a session.
Session -> NonNegativeInt
app
Create an app with a root agent.
(NonEmptyString, Spec) -> App
with-app-workflow
Attach a workflow to an app.
(App, Workflow) -> App
with-app-hooks
Attach lifecycle hooks to an app.
(App, RunHooks) -> App
runner
Create a runner with empty in-memory stores.
App -> Runner
with-runner-session-store
Replace the runner session store.
(Runner, SessionStore) -> Runner
with-runner-artifact-store
Replace the runner artifact store.
(Runner, ArtifactStore) -> Runner
with-runner-memory-store
Replace the runner memory store.
(Runner, MemoryStore) -> Runner
runner-session
Load or create the runner session for a user.
(Runner, NonEmptyString) -> Session
run-app-turn
Run one app turn and persist the resulting session.
(Runner, NonEmptyString, String, Model) -> RunnerTurn
run-app-workflow
Run an app workflow and persist the resulting session.
(Runner, NonEmptyString, String) -> Result RunnerWorkflowTurn String
Mode
Agent execution mode.
Variants
ChatTaskSingleTurnToolValueType
Tool parameter value type.
Variants
ToolStringToolIntToolFloatToolBoolToolJsonToolAnyEvent
Agent event stream entry.
Variants
UserMessage {content}AgentMessage {agent, content}ToolCall {id, agent, name, args}ToolResult {id, name, output}StateDelta {changes}Transfer {to}Escalate {reason}ArtifactDelta {key, version}NeedsInput {prompt}AgentError {message}EndOfAgent {agent}Action
Action requested by a model or planner.
This mirrors ADK-style event actions while staying provider-neutral.
Variants
Respond {content}CallTool {id, name, args}PatchState {changes}TransferToAgent {agent}EscalateRun {reason}RequestUserInput {prompt}StopAgentModel
Model adapter used by the local runner.
Variants
Model {name, run}BeforeRun
Decision returned by a before-run hook.
Variants
UseModelUseAction {Action}Plugin
Named lifecycle integration.
Variants
Plugin {name, hooks}Edge
Directed workflow edge between named agents.
Variants
Edge {source, target}AppWorkflow
Optional workflow configured for an app.
Variants
NoWorkflowUseWorkflow {Workflow}model
Create a model adapter.
(NonEmptyString, Context -> Result Action String) -> Model
text-model
Create a text-only model adapter.
(NonEmptyString, Context -> Result String String) -> Model
no-hooks
Hooks that leave runner behavior unchanged.
RunHooks
run-hooks
Create runner lifecycle hooks.
(Context -> Result BeforeRun String, Event -> Result Event String, (Context, RunResult) -> Result RunResult String) -> RunHooks
compose-hooks
Compose two hook sets in order.
(RunHooks, RunHooks) -> RunHooks
plugin
Create a named plugin from hooks.
(NonEmptyString, RunHooks) -> Plugin
plugin-stack
Create an empty plugin stack.
() -> PluginStack
with-plugin
Append a plugin to a stack.
(PluginStack, Plugin) -> PluginStack
plugin-stack-hooks
Compose hooks from all plugins in stack order.
PluginStack -> RunHooks
action-to-event
Convert an action into the event it records.
(Spec, Action) -> Event
run-action
Apply an action to a session.
(Spec, Session, Action) -> RunResult
run-turn
Run one model-backed agent turn.
(Spec, Session, String, Model) -> RunResult
run-action-with-hooks
Run an action while applying hook event transforms.
(Spec, Session, Action, RunHooks) -> RunResult
run-turn-with-hooks
Run one model-backed agent turn with lifecycle hooks.
(Spec, Session, String, Model, RunHooks) -> RunResult
runtime
Create a runtime entry for an agent/model pair.
(Spec, Model) -> Runtime
edge
Create a directed workflow edge.
(NonEmptyString, NonEmptyString) -> Edge
workflow
Create a workflow with a start agent and runtimes.
(NonEmptyString, NonEmptyString, List Runtime) -> Workflow
with-edge
Add an allowed transfer edge to a workflow.
(Workflow, Edge) -> Workflow
with-max-steps
Set a workflow max-step guard.
(Workflow, PositiveInt) -> Workflow
find-runtime
Find a runtime by agent name.
(List Runtime, NonEmptyString) -> Option Runtime
has-edge?
Return true when an edge allows source to transfer to target.
(List Edge, NonEmptyString, NonEmptyString) -> Bool
last-event
Return the last event in a session.
Session -> Option Event
run-workflow
Run a workflow from its start agent.
(Workflow, Session, String) -> WorkflowResult