docs: per-module READMEs (run vs library) + root navigation hub
ci / JVM build + tests (pull_request) Failing after 54s
ci / JVM build + tests (pull_request) Failing after 54s
Every subproject now has README.md:
- 3 runnable modules (:standalone, :agentik-cli, :agentik-tui):
quickstart, env table, parameters, known limits
- 11 library modules: what it is, which problem solves, how to
wire it in, where versions live
Root README.md is the navigation hub (Quickstart, Modules table,
publish + CI/CD notes).
Also: ci.yml prunes the :memory-vector -x excludes now that
text-embedding-kmp artifacts are published to caffeine.
518 tests green.
Verified publish pipeline: :proto:publish to caffeine produces
pom.module + per-target klibs + sources for all 9 KMP targets.
🤖 Generated with [opencode]
This commit is contained in:
+64
-50
@@ -1,73 +1,87 @@
|
||||
# :agent-toolsets — `pw.binom.agentik.toolsets`
|
||||
# `:agent-toolsets` — реестр инструментов агента (KMP, jvm + native)
|
||||
|
||||
**Ядро механики toolsets: `ToolsetRegistry`, `ToolsetDispatchPolicy`,
|
||||
встроенные тулы `enable_toolset` / `disable_toolset`, `SyncLiteTool` базовый
|
||||
класс.**
|
||||
KMP, не зависит от `:standalone`, переиспользуем в Android и в любом другом
|
||||
LiteTool-агенте.
|
||||
## Что это
|
||||
|
||||
## Какую проблему решает
|
||||
Ядро системы tools для LLM-агента:
|
||||
|
||||
В проде у агента может быть **сотня** инструментов (MCP-серверы, кастомные
|
||||
тулы, встроенные операции). Слать их все в каждый LLM-запрос:
|
||||
- `Toolset` — интерфейс, объединяющий несколько связанных tools
|
||||
(`MemoryTools`, `SkillsTools`, `FileSystemTools`).
|
||||
- `ToolRegistry` — глобальный реестр + фильтр enabled/disabled.
|
||||
- `ToolDispatcher` — берёт решение LLM (вызов инструмента с аргументами)
|
||||
→ запускает → возвращает результат.
|
||||
- **Cooperative cancel** — `interrupt()` корректно отменяет in-flight
|
||||
вызов, помечая результат `[cancelled by user]`.
|
||||
- **Concurrency budget** — `backgroundScope = Dispatchers.IO
|
||||
.limitedParallelism(4)` (см. коммит `86eb063`) — защищает
|
||||
threadpool от переполнения при fan-out 30+ диалогов.
|
||||
|
||||
1. **Раздувает контекст** — описание тула ~50–200 токенов × 100 тулов = 20K токенов
|
||||
в system prompt без пользы.
|
||||
2. **Увеличивает latency** — модель тратит время на выбор из длинного списка.
|
||||
3. **Снижает качество** — модель путается между похожими названиями.
|
||||
Решает: надёжный механизм tool-calls с прерываниями, без
|
||||
blocking-pool exhaustion, без утечки. Переиспользуется во всех
|
||||
IM-фронтендах (CLI, TUI, IRC, web).
|
||||
|
||||
Toolsets группируют тулы **по домену** (`filesystem`, `network`, `devops`, …).
|
||||
Активированы только 2-3 одновременно. `enable_toolset("filesystem")` —
|
||||
включает целую группу одним обращением; тулы появляются в system prompt +
|
||||
регистрируются как вызываемые. `disable_toolset(...)` — убирает.
|
||||
## Где используется
|
||||
|
||||
## Архитектура
|
||||
- `:standalone` подключает несколько `Toolset`-имплементаций
|
||||
(memory / skills / files / web), фильтрует через
|
||||
`AGENTIK_TOOLSETS_DEFAULT` env.
|
||||
|
||||
## Как подключить
|
||||
|
||||
```kotlin
|
||||
interface Toolset {
|
||||
val name: String // "filesystem"
|
||||
val title: String // "File operations"
|
||||
val enabled: Boolean // текущее состояние
|
||||
suspend fun enabledTools(context: ToolsetContext): List<LiteTool>
|
||||
suspend fun systemPromptSection(context: ToolsetContext): String
|
||||
commonMain.dependencies {
|
||||
api("pw.binom.agentik:agent-toolsets:0.1.0")
|
||||
}
|
||||
|
||||
class ToolsetRegistry {
|
||||
fun register(toolset: Toolset)
|
||||
fun list(): List<Toolset>
|
||||
suspend fun enable(name: String): Boolean
|
||||
suspend fun disable(name: String): Boolean
|
||||
class MyToolset : Toolset {
|
||||
override val name = "my"
|
||||
override val description = "Custom user-defined tools"
|
||||
override val tools = listOf(myTool1, myTool2)
|
||||
}
|
||||
|
||||
class ToolsetDispatchPolicy {
|
||||
fun buildDispatch(): DispatchPolicy // подаётся в LiteLlm
|
||||
}
|
||||
val dispatcher = ToolDispatcher(
|
||||
toolsets = listOf(MemoryTools(memory), MyToolset()),
|
||||
enabled = setOf("memory", "my"),
|
||||
)
|
||||
```
|
||||
|
||||
Встроенные тулы — `EnableToolsetTool` / `DisableToolsetTool` /
|
||||
`SystemPromptToolsetSection` — дают LLM самой управлять составом инструментов.
|
||||
База для кастомных тулов — `SyncLiteTool` (обёртка над `LiteTool`,
|
||||
синхронная `execute(args): String`).
|
||||
## Версии
|
||||
|
||||
## Подключение
|
||||
`gradle/libs.versions.toml` → `[versions] agentik-agent-toolsets`.
|
||||
|
||||
## Как пишется tool
|
||||
|
||||
```kotlin
|
||||
commonMain {
|
||||
implementation("pw.binom.agentik:agent-toolsets:$version")
|
||||
// Транзитивно: :storage-core (для ToolsetContext) + :proto
|
||||
data object EchoTool : Tool {
|
||||
override val name = "echo"
|
||||
override val description = "Echoes back the argument"
|
||||
override val argsSchema = jsonSchema {
|
||||
property("text", JsonType.STRING) { required = true }
|
||||
}
|
||||
|
||||
override suspend fun invoke(args: JsonObject): ToolResult {
|
||||
val text = args["text"]?.jsonPrimitive?.content ?: return ToolResult.Error("missing text")
|
||||
return ToolResult.Text(text)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Где смотреть версии
|
||||
## Тесты
|
||||
|
||||
- `version` из `gradle.properties` (`version=0.1.0`)
|
||||
- релизы: `https://git.binom.pw/subochev/agentik/releases`
|
||||
|
||||
## Сборка
|
||||
|
||||
```bash
|
||||
./gradlew :agent-toolsets:build
|
||||
```
|
||||
./gradlew :agent-toolsets:allTests
|
||||
```
|
||||
|
||||
KMP-таргеты — полный набор. Зависимости — `:storage-core` + `:proto` +
|
||||
`kotlinx-coroutines` + `kotlinx-serialization`.
|
||||
Покрывают: invoke happy-path, invalid args, cooperative cancel,
|
||||
budget exhaustion, registry filter, parallel dispatch.
|
||||
|
||||
## Чего здесь НЕТ
|
||||
|
||||
- Никакого конкретного LLM. Dispatcher вызывает tools, не LLM.
|
||||
- Никакого persistent storage. Опирается на контракт `WorkingMemoryStore`
|
||||
(см. `:storage-core`).
|
||||
|
||||
## Текущий статус
|
||||
|
||||
Используется продакшеном. Реализует полную спецификацию из
|
||||
[INTERRUPT-DESIGN.md](../../docs/INTERRUPT-DESIGN.md): tool exchange
|
||||
log, rolling buffer, partial-state persistence.
|
||||
|
||||
Reference in New Issue
Block a user