palapa-agent 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. palapa_agent-0.1.0/.claude/settings.local.json +18 -0
  2. palapa_agent-0.1.0/.gitignore +7 -0
  3. palapa_agent-0.1.0/.python-version +1 -0
  4. palapa_agent-0.1.0/AGENTS.md +83 -0
  5. palapa_agent-0.1.0/CONTEXT.md +99 -0
  6. palapa_agent-0.1.0/PKG-INFO +244 -0
  7. palapa_agent-0.1.0/PRD.md +131 -0
  8. palapa_agent-0.1.0/README.md +210 -0
  9. palapa_agent-0.1.0/clab-ospf-routing/clab-ospf-routing-demo/.state.clab.yaml +61 -0
  10. palapa_agent-0.1.0/clab-ospf-routing/clab-ospf-routing-demo/.tls/ca/ca.key +27 -0
  11. palapa_agent-0.1.0/clab-ospf-routing/clab-ospf-routing-demo/.tls/ca/ca.pem +22 -0
  12. palapa_agent-0.1.0/clab-ospf-routing/clab-ospf-routing-demo/ansible-inventory.yml +19 -0
  13. palapa_agent-0.1.0/clab-ospf-routing/clab-ospf-routing-demo/authorized_keys +1 -0
  14. palapa_agent-0.1.0/clab-ospf-routing/clab-ospf-routing-demo/nornir-simple-inventory.yml +26 -0
  15. palapa_agent-0.1.0/clab-ospf-routing/clab-ospf-routing-demo/topology-data.json +258 -0
  16. palapa_agent-0.1.0/clab-ospf-routing/ospf-lab.yaml +38 -0
  17. palapa_agent-0.1.0/clab-static-routing/clab-static-routing-demo/.state.clab.yaml +44 -0
  18. palapa_agent-0.1.0/clab-static-routing/clab-static-routing-demo/.tls/ca/ca.key +27 -0
  19. palapa_agent-0.1.0/clab-static-routing/clab-static-routing-demo/.tls/ca/ca.pem +22 -0
  20. palapa_agent-0.1.0/clab-static-routing/clab-static-routing-demo/ansible-inventory.yml +17 -0
  21. palapa_agent-0.1.0/clab-static-routing/clab-static-routing-demo/authorized_keys +1 -0
  22. palapa_agent-0.1.0/clab-static-routing/clab-static-routing-demo/nornir-simple-inventory.yml +21 -0
  23. palapa_agent-0.1.0/clab-static-routing/clab-static-routing-demo/topology-data.json +195 -0
  24. palapa_agent-0.1.0/clab-static-routing/static-routing-lab.yaml +31 -0
  25. palapa_agent-0.1.0/config.yaml.example +143 -0
  26. palapa_agent-0.1.0/docs/adr/0001-openai-compat-over-native-sdk.md +22 -0
  27. palapa_agent-0.1.0/docs/adr/0002-semi-restricted-bash.md +31 -0
  28. palapa_agent-0.1.0/docs/adr/0003-fully-automatic-skill-extraction.md +23 -0
  29. palapa_agent-0.1.0/docs/adr/0004-system-prompt-frozen-per-session.md +22 -0
  30. palapa_agent-0.1.0/docs/adr/0005-skill-trigger-and-format.md +37 -0
  31. palapa_agent-0.1.0/docs/adr/0006-agent-loop-session-lifecycle-and-api-model.md +38 -0
  32. palapa_agent-0.1.0/docs/adr/0007-context-compaction-and-grace-call.md +45 -0
  33. palapa_agent-0.1.0/docs/adr/0008-mcp-client-support.md +22 -0
  34. palapa_agent-0.1.0/docs/adr/0009-network-device-management.md +57 -0
  35. palapa_agent-0.1.0/docs/adr/0010-agent-delegation.md +97 -0
  36. palapa_agent-0.1.0/docs/adr/0011-agent-persona-soul-md.md +34 -0
  37. palapa_agent-0.1.0/palapa/__init__.py +0 -0
  38. palapa_agent-0.1.0/palapa/agent/__init__.py +0 -0
  39. palapa_agent-0.1.0/palapa/agent/core.py +468 -0
  40. palapa_agent-0.1.0/palapa/agent/evaluator.py +210 -0
  41. palapa_agent-0.1.0/palapa/bundled_skills/analyze-bgp-instability/SKILL.md +45 -0
  42. palapa_agent-0.1.0/palapa/bundled_skills/batch-router-inventory-bgp-monitor/SKILL.md +25 -0
  43. palapa_agent-0.1.0/palapa/bundled_skills/containerlab-static-routing-config/SKILL.md +38 -0
  44. palapa_agent-0.1.0/palapa/bundled_skills/discover-managed-devices/SKILL.md +33 -0
  45. palapa_agent-0.1.0/palapa/bundled_skills/mikrotik-bgp-aspath-investigation/SKILL.md +29 -0
  46. palapa_agent-0.1.0/palapa/bundled_skills/mikrotik-bgp-export-filter-audit/SKILL.md +78 -0
  47. palapa_agent-0.1.0/palapa/bundled_skills/mikrotik-bgp-route-dump/SKILL.md +84 -0
  48. palapa_agent-0.1.0/palapa/bundled_skills/mikrotik-bgp-route-verification/SKILL.md +67 -0
  49. palapa_agent-0.1.0/palapa/bundled_skills/mikrotik-daily-network-brief/SKILL.md +51 -0
  50. palapa_agent-0.1.0/palapa/bundled_skills/mikrotik-large-bgp-route-collection/SKILL.md +59 -0
  51. palapa_agent-0.1.0/palapa/bundled_skills/mikrotik-verified-commands/SKILL.md +197 -0
  52. palapa_agent-0.1.0/palapa/bundled_skills/monitor-router-system-logs/SKILL.md +28 -0
  53. palapa_agent-0.1.0/palapa/bundled_skills/netbox-api-integration/SKILL.md +185 -0
  54. palapa_agent-0.1.0/palapa/bundled_skills/network-as-path-mapping/SKILL.md +37 -0
  55. palapa_agent-0.1.0/palapa/bundled_skills/network-device-health-diagnosis/SKILL.md +27 -0
  56. palapa_agent-0.1.0/palapa/bundled_skills/network-mikrotik-troubleshooting/SKILL.md +32 -0
  57. palapa_agent-0.1.0/palapa/bundled_skills/troubleshoot-bgp-routing/SKILL.md +87 -0
  58. palapa_agent-0.1.0/palapa/config.py +203 -0
  59. palapa_agent-0.1.0/palapa/gateway/__init__.py +0 -0
  60. palapa_agent-0.1.0/palapa/gateway/api.py +115 -0
  61. palapa_agent-0.1.0/palapa/gateway/cli.py +604 -0
  62. palapa_agent-0.1.0/palapa/gateway/runtime.py +163 -0
  63. palapa_agent-0.1.0/palapa/mcp/__init__.py +0 -0
  64. palapa_agent-0.1.0/palapa/mcp/client.py +194 -0
  65. palapa_agent-0.1.0/palapa/mcp/security.py +94 -0
  66. palapa_agent-0.1.0/palapa/mcp/tool.py +41 -0
  67. palapa_agent-0.1.0/palapa/memory/__init__.py +0 -0
  68. palapa_agent-0.1.0/palapa/memory/audit.py +30 -0
  69. palapa_agent-0.1.0/palapa/memory/session.py +39 -0
  70. palapa_agent-0.1.0/palapa/memory/skills.py +187 -0
  71. palapa_agent-0.1.0/palapa/memory/soul.py +53 -0
  72. palapa_agent-0.1.0/palapa/memory/tracer.py +42 -0
  73. palapa_agent-0.1.0/palapa/memory/user_model.py +104 -0
  74. palapa_agent-0.1.0/palapa/providers/__init__.py +0 -0
  75. palapa_agent-0.1.0/palapa/providers/base.py +25 -0
  76. palapa_agent-0.1.0/palapa/providers/ollama.py +48 -0
  77. palapa_agent-0.1.0/palapa/setup/__init__.py +0 -0
  78. palapa_agent-0.1.0/palapa/setup/devices.py +58 -0
  79. palapa_agent-0.1.0/palapa/setup/skills.py +40 -0
  80. palapa_agent-0.1.0/palapa/setup/skills_git.py +169 -0
  81. palapa_agent-0.1.0/palapa/setup/wizard.py +76 -0
  82. palapa_agent-0.1.0/palapa/tools/__init__.py +0 -0
  83. palapa_agent-0.1.0/palapa/tools/base.py +11 -0
  84. palapa_agent-0.1.0/palapa/tools/bash.py +167 -0
  85. palapa_agent-0.1.0/palapa/tools/browser.py +38 -0
  86. palapa_agent-0.1.0/palapa/tools/delegate.py +328 -0
  87. palapa_agent-0.1.0/palapa/tools/file.py +59 -0
  88. palapa_agent-0.1.0/palapa/tools/memory.py +85 -0
  89. palapa_agent-0.1.0/palapa/tools/network.py +157 -0
  90. palapa_agent-0.1.0/palapa/tools/network_whitelist.py +113 -0
  91. palapa_agent-0.1.0/palapa/tools/registry.py +35 -0
  92. palapa_agent-0.1.0/palapa/tools/skill_script.py +130 -0
  93. palapa_agent-0.1.0/palapa/tools/web_fetch.py +28 -0
  94. palapa_agent-0.1.0/palapa/tools/web_search.py +33 -0
  95. palapa_agent-0.1.0/pyproject.toml +54 -0
  96. palapa_agent-0.1.0/reports/bgp-analysis-gate-idren-ub-2026-09.md +166 -0
  97. palapa_agent-0.1.0/reports/incident-report-bgp-flapping-brin-20260813.md +39 -0
  98. palapa_agent-0.1.0/reports/report-analysis-fo-optimization-brin-ub.md +42 -0
  99. palapa_agent-0.1.0/tests/conftest.py +21 -0
  100. palapa_agent-0.1.0/tests/fixtures/mcp_echo_server.py +31 -0
  101. palapa_agent-0.1.0/tests/integration/test_agent_loop_integration.py +43 -0
  102. palapa_agent-0.1.0/tests/integration/test_api_integration.py +109 -0
  103. palapa_agent-0.1.0/tests/integration/test_cli_integration.py +38 -0
  104. palapa_agent-0.1.0/tests/integration/test_evaluator_integration.py +174 -0
  105. palapa_agent-0.1.0/tests/integration/test_mcp_client_integration.py +71 -0
  106. palapa_agent-0.1.0/tests/integration/test_network_tool_integration.py +71 -0
  107. palapa_agent-0.1.0/tests/integration/test_ollama_provider_integration.py +22 -0
  108. palapa_agent-0.1.0/tests/integration/test_user_model_consolidation_integration.py +39 -0
  109. palapa_agent-0.1.0/tests/integration/test_web_search_tool_integration.py +12 -0
  110. palapa_agent-0.1.0/tests/unit/test_agent_loop.py +497 -0
  111. palapa_agent-0.1.0/tests/unit/test_api.py +121 -0
  112. palapa_agent-0.1.0/tests/unit/test_audit_log.py +48 -0
  113. palapa_agent-0.1.0/tests/unit/test_bash_tool.py +203 -0
  114. palapa_agent-0.1.0/tests/unit/test_browser_tool.py +22 -0
  115. palapa_agent-0.1.0/tests/unit/test_cli.py +201 -0
  116. palapa_agent-0.1.0/tests/unit/test_cli_skills_sessions.py +188 -0
  117. palapa_agent-0.1.0/tests/unit/test_config.py +434 -0
  118. palapa_agent-0.1.0/tests/unit/test_delegate_tool.py +626 -0
  119. palapa_agent-0.1.0/tests/unit/test_devices_commands.py +89 -0
  120. palapa_agent-0.1.0/tests/unit/test_evaluator.py +312 -0
  121. palapa_agent-0.1.0/tests/unit/test_file_tool.py +52 -0
  122. palapa_agent-0.1.0/tests/unit/test_install_defaults.py +60 -0
  123. palapa_agent-0.1.0/tests/unit/test_mcp_config.py +39 -0
  124. palapa_agent-0.1.0/tests/unit/test_mcp_security.py +45 -0
  125. palapa_agent-0.1.0/tests/unit/test_memory_tool.py +58 -0
  126. palapa_agent-0.1.0/tests/unit/test_network_tool.py +230 -0
  127. palapa_agent-0.1.0/tests/unit/test_network_whitelist.py +57 -0
  128. palapa_agent-0.1.0/tests/unit/test_ollama_provider.py +88 -0
  129. palapa_agent-0.1.0/tests/unit/test_runtime.py +110 -0
  130. palapa_agent-0.1.0/tests/unit/test_session_store.py +51 -0
  131. palapa_agent-0.1.0/tests/unit/test_skill_script.py +175 -0
  132. palapa_agent-0.1.0/tests/unit/test_skills_git.py +183 -0
  133. palapa_agent-0.1.0/tests/unit/test_skills_library.py +527 -0
  134. palapa_agent-0.1.0/tests/unit/test_soul_model.py +68 -0
  135. palapa_agent-0.1.0/tests/unit/test_tool_dispatcher.py +72 -0
  136. palapa_agent-0.1.0/tests/unit/test_user_model.py +123 -0
  137. palapa_agent-0.1.0/tests/unit/test_web_fetch_tool.py +16 -0
  138. palapa_agent-0.1.0/tests/unit/test_wizard.py +109 -0
  139. palapa_agent-0.1.0/uv.lock +2079 -0
@@ -0,0 +1,18 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(git *)",
5
+ "Bash(systemctl is-active *)",
6
+ "Bash(curl -s http://localhost:11434/api/tags)",
7
+ "Bash(curl -s -m 5 http://10.45.185.253:11494/v1/models)",
8
+ "Bash(uv run *)",
9
+ "Bash(uv pip *)",
10
+ "Bash(uv cache *)",
11
+ "Read(//home/alan/.cache/uv/**)",
12
+ "Bash(uvx mcp-server-time *)",
13
+ "Bash(uvx --no-cache --refresh mcp-server-time --help)",
14
+ "Bash(uvx *)",
15
+ "Bash(python3 *)"
16
+ ]
17
+ }
18
+ }
@@ -0,0 +1,7 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ config.yaml
5
+ .env
6
+ .pytest_cache/
7
+ *.egg-info/
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,83 @@
1
+ # Palapa — Agent Instructions
2
+
3
+ Palapa is a locally-running autonomous AI agent framework built in Python. It runs against Ollama models via the OpenAI-compatible endpoint and uses a three-layer memory system (episodic, semantic, procedural). Read `CONTEXT.md` for domain terminology before making changes.
4
+
5
+ ## Relationship to palapa-wiki
6
+
7
+ This repo (`palapa-agent/`) is basecode only — implementation, not planning. All research, architecture decisions, and Fase/progress tracking live in the sibling repo `../palapa-wiki/` (governed by its own `CLAUDE.md`, not this file).
8
+
9
+ Before implementing anything non-trivial here, check `palapa-wiki/wiki/overview.md` for current Fase status and `palapa-wiki/wiki/architecture/` + `palapa-wiki/wiki/research/` for the decisions that should inform the approach. Every entry in this file (setup, the architecture table below, code conventions) reflects a decision already recorded in palapa-wiki — it is not invented here. If a change in this repo implies a new convention or design decision, record it in palapa-wiki first (or in the same session), then update this file to match — don't let the two drift apart.
10
+
11
+ GitHub milestones/issues for this repo are also managed from palapa-wiki's side (its `CLAUDE.md` "Sinkronisasi GitHub milestone/issue" workflow) — this file doesn't duplicate that procedure.
12
+
13
+ Standing rules from the user (recorded in palapa-wiki's `CLAUDE.md` under "Aturan Tetap dari Feedback User") apply in this repo too. The ones that matter most when working from here:
14
+
15
+ - **Milestone before code** — always create the GitHub milestone before starting any fase implementation, no matter how small.
16
+ - **Pros AND cons for every option** — when presenting design or implementation choices, spell out trade-offs for each option, not just descriptions.
17
+
18
+ ## Setup
19
+
20
+ ```bash
21
+ uv sync # install dependencies
22
+ cp config.yaml.example config.yaml # first-time setup
23
+ ```
24
+
25
+ Requires Ollama running locally with a tool-calling capable model (e.g. `qwen3.6:27b`).
26
+
27
+ ## Commands
28
+
29
+ ```bash
30
+ uv run pytest # run all tests
31
+ uv run pytest tests/integration/ # integration tests only (requires Ollama)
32
+ uv run pytest tests/unit/ # unit tests only (no Ollama needed)
33
+
34
+ uv run palapa chat # start interactive CLI session
35
+ uv run palapa chat --once "message" # single scripted turn, no REPL
36
+ uv run uvicorn palapa.gateway.api:app --reload # start REST API (host/port from config.yaml `api:` section)
37
+ uv run palapa skills list # list all skills
38
+ uv run palapa skills show <name> # print a skill's content
39
+ uv run palapa skills delete <name> # delete a skill
40
+ uv run palapa sessions search <query> # query episodic memory (SQLite FTS5)
41
+ ```
42
+
43
+ ## Architecture
44
+
45
+ | Component | Responsibility |
46
+ |-----------|---------------|
47
+ | `agent/core.py` | ReAct agent loop — builds prompt, calls LLM, dispatches tools, repeats |
48
+ | `agent/evaluator.py` | Post-session skill extractor — scores complexity, writes skill files with `auto_extracted` marker, update-or-new LLM decision, never overwrites user-created skills |
49
+ | `tools/` | One file per tool: `bash`, `file`, `web_search`, `web_fetch`, `browser`, `memory` |
50
+ | `tools/registry.py` | Tool registration and schema aggregation for LLM |
51
+ | `memory/session.py` | SQLite FTS5 episodic memory — stores and searches past sessions |
52
+ | `memory/user_model.py` | Reads and writes `USER.md` and `MEMORY.md` |
53
+ | `memory/skills.py` | Agent Skills store — folder format (`{slug}/SKILL.md`), dual dirs (global + `.palapa/skills/`), auto-migration from flat `.md`, relevance matching |
54
+ | `providers/ollama.py` | OpenAI-compat adapter — wraps `openai` SDK with configurable `base_url` |
55
+ | `gateway/runtime.py` | Shared collaborator wiring (`build_agent_loop`) — used by both `gateway/cli.py` and `gateway/api.py` |
56
+ | `gateway/` | Gateway layer — user-facing entry points ke agent |
57
+ | `gateway/cli.py` | `palapa chat` — interactive REPL / `--once` scripted mode |
58
+ | `gateway/api.py` | FastAPI REST API — `POST /chat` (SSE streaming, stateless per ADR-0006), `GET /skills`, `GET /health` |
59
+ | `config.yaml` | Runtime config: model name, base URL, tool flags, memory paths, API host/port |
60
+
61
+ Flow: `AgentLoop.run(message)` → build system prompt (config + USER.md + relevant skills + episodic hits) → LLM call → parse tool calls → `ToolDispatcher.dispatch()` → feed results back → repeat until final response or max iterations.
62
+
63
+ ## Code Conventions
64
+
65
+ - **Type hints required** on all function signatures — no bare `def f(x)`.
66
+ - **Pydantic v2** for anything validated from external input (config, LLM output) — e.g. `PalapaConfig`, `EvaluatorConfig`. Plain `@dataclass` is fine for internal, read-only containers that never validate raw input (e.g. `SkillMeta` in `memory/skills.py`, built from already-parsed YAML). When in doubt, default to Pydantic.
67
+ - **No comments except non-obvious WHY** — code must be self-documenting via naming. Never explain what the code does; only explain hidden constraints, subtle invariants, or workarounds.
68
+ - Python 3.11+. Use `uv` for dependency management — do not use `pip` directly.
69
+
70
+ ## Do
71
+
72
+ - Read `CONTEXT.md` to understand domain terms before writing or renaming anything.
73
+ - Use the `Provider` ABC when adding new LLM backends — never call `openai` directly from the Agent Loop.
74
+ - Write tests at the highest seam possible: prefer `AgentLoop.run()` integration tests over unit tests of internal steps.
75
+ - Keep tool implementations stateless — side effects only, no internal state between calls.
76
+
77
+ ## Do Not
78
+
79
+ - **Do not modify `config.yaml`** — it is the user's runtime config, not a project file.
80
+ - **Do not hardcode model names** — always read from config. The model is user-controlled.
81
+ - **Do not write to `~/.palapa/`** — that is the user's runtime data directory. Tests must use temp directories.
82
+ - **Do not run the agent loop directly** during development or tests without explicit isolation — it can trigger real bash execution, browser automation, and filesystem writes.
83
+ - **Do not add dependencies** without checking `pyproject.toml` first and confirming the addition is necessary.
@@ -0,0 +1,99 @@
1
+ # Palapa — Domain Glossary
2
+
3
+ ## Core Concepts
4
+
5
+ **Agent Loop**
6
+ Owns both a Session's lifecycle and the ReAct-style execution of each Turn within it — one class, mirroring Hermes Agent's `AIAgent` (see ADR-0006). Per Session: assembles the system prompt once at start (Semantic + Procedural + Episodic Memory) and keeps it frozen; accumulates conversation history across Turns; when the session closes, persists it (Episodic Memory) and invokes the Evaluator in the background. Per Turn: call LLM → parse tool calls → dispatch tools → feed results back → repeat until a final response or a configured max iteration count is reached.
7
+
8
+ **Tool**
9
+ A discrete, named capability the Agent Loop can invoke. Each tool exposes a JSON schema for the LLM and an `execute()` implementation. Tools are stateless; side effects are their whole purpose.
10
+
11
+ **Skill**
12
+ A reusable reasoning pattern extracted automatically after a complex task completes. Stored as a `.md` file in `skills/`. Loaded into the system prompt at the start of each session if deemed relevant. Distinct from a Tool — a Skill is prose guidance, not executable code.
13
+
14
+ **Turn**
15
+ One call to the Agent Loop for a single user message — the full ReAct cycle (which may include several internal tool-call iterations) needed to produce one final response. A Session is composed of one or more Turns.
16
+ _Avoid_: "task" — Hermes Agent's own docs use "task" for two unrelated things (the skill-extraction trigger, and its `/background` sub-sessions); Palapa doesn't use "task" as a domain term to avoid the same overload.
17
+
18
+ **Grace Call**
19
+ One extra, otherwise-identical iteration granted at the end of a Turn when its iteration budget is exhausted, in place of an immediate hard stop — the model can still call a tool if it wants to; nothing is forced or restricted. After that one bonus iteration the loop stops regardless of outcome. Mirrors Hermes Agent's actual `agent/conversation_loop.py` mechanism, verified from source (ADR-0007).
20
+
21
+ **Context Compaction**
22
+ The process of shortening an Agent Loop's accumulated message history once it crosses a threshold of `context_length`, so a long Session doesn't overflow the model's context window. Always preserves the most recent messages intact and keeps a tool-call and its result together as one unit; anything compacted away is persisted to Episodic Memory first. Two thresholds trigger it, at increasing aggressiveness (ADR-0007).
23
+
24
+ **Session**
25
+ One continuous interaction from the user's first message until the user ends the conversation, composed of one or more Turns. Sessions are summarized and persisted to Episodic Memory, and evaluated by the Evaluator for Skill extraction, when the session closes — not after each Turn.
26
+
27
+ **Provider**
28
+ An adapter that wraps an LLM backend behind a common interface. The default Provider targets an Ollama instance via the OpenAI-compatible endpoint (`/v1`). Swapping providers must not require changes to the Agent Loop.
29
+
30
+ **Config**
31
+ A `config.yaml` file at the project root controlling: model name, provider base URL, context length, tool enable/disable flags, and memory paths.
32
+
33
+ ## Memory Layers
34
+
35
+ **Episodic Memory**
36
+ A SQLite database with FTS5 full-text search storing summarized past sessions. The Agent Loop queries it at session start to retrieve relevant prior context.
37
+
38
+ **Semantic Memory**
39
+ Two flat files:
40
+ - `USER.md` — persistent model of the user: preferences, expertise, recurring goals.
41
+ - `MEMORY.md` — general facts the agent has learned that aren't user-specific.
42
+
43
+ **Procedural Memory**
44
+ The `skills/` directory. Each `.md` file encodes a named, reusable task pattern. Skills are auto-extracted by the Evaluator after complex tasks.
45
+
46
+ ## Components
47
+
48
+ **Evaluator**
49
+ A post-session subprocess that assesses whether a completed Session was complex and novel enough to warrant Skill extraction. If yes, calls the LLM to write a Skill file. Runs fully automatically — no user confirmation.
50
+
51
+ **Tool Dispatcher**
52
+ Receives parsed tool-call requests from the LLM response, routes them to the correct Tool implementation, enforces the semi-restricted bash policy, and returns results.
53
+
54
+ **Semi-Restricted Bash Policy**
55
+ Non-destructive shell commands execute immediately. Destructive commands (those matching a configured danger pattern: `rm`, `sudo`, `dd`, `mkfs`, `chmod -R`, etc.) require explicit user confirmation before execution.
56
+
57
+ ## MCP (Model Context Protocol)
58
+
59
+ **MCP Server**
60
+ An external tool provider the user configures under `mcp_servers` in Config — either a local subprocess (stdio transport) or a remote endpoint (HTTP transport). Trust is established once, at configuration time, not per call: unlike the Semi-Restricted Bash Policy, invoking an MCP Server's tools requires no per-call confirmation. Palapa is only ever an MCP *client* — it does not expose its own Tools to other MCP clients.
61
+ _Avoid_: "MCP client" as a synonym — Palapa's MCP client is the mechanism; "MCP Server" is the thing being connected to.
62
+
63
+ **MCP Tool**
64
+ A Tool whose implementation is delegated to an MCP Server rather than Palapa's own code, discovered automatically when Palapa starts and registered into the Tool Dispatcher under the name `mcp_{server}_{tool}`. Functionally a Tool like any other — the Agent Loop cannot tell the difference.
65
+
66
+ ## Agent Delegation
67
+
68
+ **Agent Preset**
69
+ A named specialist configuration declared in `config.yaml` under `delegation.agents`. Each preset specifies: which Tools the child may use (`tools`), an optional override model (`model`), an optional per-task timeout in seconds (`timeout`, default 120), and whether those tools are hidden from the main agent (`exclusive`). Trust is established at config time, not at call time.
70
+
71
+ **`delegate_task` (singular)**
72
+ Existing tool (Fase 12). Spawns one child Agent Loop synchronously with a named preset, returns the child's final message as a string. Use for a single bounded sub-task.
73
+
74
+ **`delegate_tasks` (plural)**
75
+ New tool (Fase 16). Takes a list of labeled sub-tasks `[{label, goal, context, agent}, ...]`, spawns all children in parallel (up to `delegation.max_parallel` at a time, default 2), and returns a dict keyed by label once all finish. Failed children return an `"ERROR: ..."` string for their label — other children are not cancelled. Use when multiple independent sub-tasks can run concurrently.
76
+ _Avoid_: "parallel delegate_task" — the tool name is `delegate_tasks` (plural), a distinct tool from `delegate_task`.
77
+
78
+ **Parallel Delegation**
79
+ The pattern of using `delegate_tasks` to run multiple specialist children concurrently. Each child is an ephemeral Agent Loop with its preset's tool registry and a minimal system prompt. Children do not share state, cannot communicate with each other, and results are collected only after all children finish (or timeout).
80
+
81
+ **`max_parallel`**
82
+ A `DelegationConfig`-level integer (default 2) capping how many child threads `delegate_tasks` may spawn simultaneously. Exists as a resource safety valve for local Ollama deployments where each child competes for GPU VRAM.
83
+
84
+ ## Agent Skills
85
+
86
+ **Agent Skills standard**
87
+ Open format (agentskills.io) for portable skill definitions — a folder named after the skill containing a `SKILL.md` file. Palapa is fully compatible: `SkillsLibrary` reads, writes, and migrates skills in this format.
88
+
89
+ **Skill folder format**
90
+ A directory named `{slug}/SKILL.md`. The `slug` is the kebab-case name, max 64 characters. The frontmatter `name` field must match the directory name exactly. Other files in the folder (scripts, assets) are ignored by `SkillsLibrary` but preserved by `delete_skill`.
91
+
92
+ **`SkillsLibrary`**
93
+ Memory module that manages the Agent Skills store. Scans both a global directory (`config.memory.skills_dir`, default `~/.palapa/skills/`) and a project-level directory (`.palapa/skills/` in CWD, convention-based, no config). Project skills override global skills on name conflict. `write_skill` and `delete_skill` target the global dir by default; `delete_skill` targets the project dir first.
94
+
95
+ **`auto_extracted` marker**
96
+ YAML field `metadata.palapa.auto_extracted: true` injected by the Evaluator into every skill it writes. Skills without this marker are treated as user-created and are never overwritten by the Evaluator — not even when a duplicate is detected. Skills with the marker may be overwritten if the Evaluator's LLM decides the new session is an improvement.
97
+
98
+ **`evaluator.model`**
99
+ Optional config field on `EvaluatorConfig`. When set, the Evaluator uses a separate `OllamaProvider` with this model name (same `base_url` as the main model) instead of the main agent's provider. Purpose: avoid quality degradation when the main model is small-parameter.
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.5
2
+ Name: palapa-agent
3
+ Version: 0.1.0
4
+ Summary: Palapa — local autonomous AI agent built on Ollama
5
+ Project-URL: Homepage, https://github.com/indi9o/palapa-agent
6
+ Project-URL: Bug Tracker, https://github.com/indi9o/palapa-agent/issues
7
+ License: MIT
8
+ Keywords: agent,ai,autonomous,llm,network-operations,ollama
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Classifier: Topic :: System :: Networking :: Monitoring
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: beautifulsoup4>=4.15.0
20
+ Requires-Dist: ddgs>=9.14.4
21
+ Requires-Dist: fastapi>=0.115.0
22
+ Requires-Dist: httpx>=0.28.1
23
+ Requires-Dist: mcp>=1.28.0
24
+ Requires-Dist: netmiko>=4.3.0
25
+ Requires-Dist: openai>=1.0
26
+ Requires-Dist: playwright>=1.61.0
27
+ Requires-Dist: prompt-toolkit>=3.0
28
+ Requires-Dist: pydantic>=2.0
29
+ Requires-Dist: python-dotenv>=1.0.0
30
+ Requires-Dist: pyyaml>=6.0
31
+ Requires-Dist: rich>=13.0
32
+ Requires-Dist: uvicorn[standard]>=0.30.0
33
+ Description-Content-Type: text/markdown
34
+
35
+ # Palapa
36
+
37
+ Autonomous AI agent lokal berbasis Ollama. Berjalan sepenuhnya offline, tanpa cloud API, dengan arsitektur yang bisa dimodifikasi bebas.
38
+
39
+ ---
40
+
41
+ ## Fitur
42
+
43
+ - **ReAct agent loop** — multi-turn, tool-calling, dengan context compaction otomatis
44
+ - **6 tools bawaan** — bash, file, web search, web fetch, browser (Playwright), memory
45
+ - **3-layer memory** — episodic (SQLite FTS5) + semantic (USER.md/MEMORY.md) + procedural (skills/)
46
+ - **Skills auto-extraction** — Evaluator otomatis menulis skill baru setelah task kompleks, tanpa konfirmasi
47
+ - **Skills portabilitas** — export skills ke git repo lokal, import dari remote, sync antar mesin
48
+ - **Agent delegation** — main agent bisa mendelegasi sub-task ke child agent specialist, paralel
49
+ - **Network tools** — Mikrotik RouterOS + Ruckus ICX + Cisco/Juniper/Aruba/Huawei via Netmiko, bundled whitelist per vendor/OS, read-only
50
+ - **MCP client** — koneksi ke MCP server eksternal (stdio + HTTP)
51
+ - **CLI interaktif** — history, multi-line input, slash commands, first-run wizard
52
+ - **REST API** — FastAPI, streaming SSE, stateless per request
53
+ - **Provider configurable** — Ollama default, swap via `model.base_url` di config
54
+
55
+ ---
56
+
57
+ ## Instalasi
58
+
59
+ ### Pengguna umum
60
+
61
+ ```bash
62
+ pip install palapa-agent
63
+ palapa chat # wizard berjalan otomatis saat pertama kali
64
+ ```
65
+
66
+ ### Developer
67
+
68
+ ```bash
69
+ git clone https://github.com/indi9o/palapa-agent
70
+ cd palapa-agent
71
+
72
+ uv sync
73
+
74
+ # Pertama kali pakai browser tool:
75
+ uv run playwright install chromium
76
+ ```
77
+
78
+ Jalankan `uv run palapa chat` — wizard otomatis muncul kalau config belum ada.
79
+
80
+ ---
81
+
82
+ ## Penggunaan
83
+
84
+ > **Catatan:** Contoh perintah di bawah menggunakan `palapa` langsung — berlaku setelah `pip install palapa-agent`.
85
+ > Kalau kamu pakai mode developer (`uv sync`), tambahkan prefix `uv run`: `uv run palapa`, `uv run palapa devices list`, dst.
86
+
87
+ ### CLI
88
+
89
+ ```bash
90
+ # Sesi interaktif
91
+ palapa
92
+
93
+ # Satu perintah, tanpa REPL
94
+ palapa --once "ringkasan interface eth0 di router X"
95
+
96
+ # Inventory perangkat jaringan
97
+ palapa devices add # tambah perangkat secara interaktif
98
+ palapa devices list # lihat daftar perangkat
99
+
100
+ # Kelola skills
101
+ palapa skills list
102
+ palapa skills show <nama>
103
+ palapa skills delete <nama>
104
+ palapa skills install-defaults # install 17 bundled starter skills
105
+ palapa skills install-defaults --overwrite
106
+
107
+ # Export/import skills antar mesin
108
+ palapa skills export --repo <path> # copy ke git repo lokal + auto-commit
109
+ palapa skills import git+<url> # clone dari remote, register sebagai sumber
110
+ palapa skills pull # update dari semua remote terdaftar
111
+ palapa skills pull <remote-name>
112
+ palapa skills remotes # lihat daftar remote terdaftar
113
+
114
+ # Cari sesi sebelumnya (episodic memory)
115
+ palapa sessions search <query>
116
+ ```
117
+
118
+ **Slash commands di dalam `palapa chat`:**
119
+
120
+ | Command | Fungsi |
121
+ |---|---|
122
+ | `/status` | Info sesi + model aktif + token usage |
123
+ | `/clear` | Reset histori percakapan |
124
+ | `/compact` | Paksa compaction konteks sekarang |
125
+ | `/verbose` | Toggle tampilan tool call raw/ringkas |
126
+ | `/audit` | Toggle audit log tool call |
127
+ | `/skills` | Daftar skills yang ter-load sesi ini |
128
+ | `/<skill-name>` | Inject skill langsung ke agent |
129
+
130
+ ### REST API
131
+
132
+ ```bash
133
+ uv run uvicorn palapa.gateway.api:app --reload
134
+ ```
135
+
136
+ ```
137
+ POST /chat — kirim pesan, respons streaming SSE
138
+ GET /skills — daftar semua skills
139
+ GET /health — health check
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Konfigurasi
145
+
146
+ Config dicari di dua lokasi (prioritas atas ke bawah):
147
+
148
+ 1. `./config.yaml` — developer, per-project
149
+ 2. `~/.palapa/config.yaml` — user install (dibuat oleh wizard)
150
+
151
+ ```yaml
152
+ model:
153
+ base_url: "http://localhost:11434/v1" # override via env PALAPA_BASE_URL
154
+ name: "qwen3.6:27b"
155
+ context_length: 64000
156
+
157
+ tools:
158
+ bash:
159
+ enabled: true
160
+ browser:
161
+ enabled: true
162
+ network:
163
+ enabled: false # aktifkan kalau pakai NetworkTool
164
+ inventory_path: "~/.palapa/inventory.yaml"
165
+ scripts_enabled: false # opt-in eksplisit untuk run_skill_script
166
+ # whitelist_extend: # tambah command di luar bundled default
167
+ # mikrotik:
168
+ # ros7: ["/my-cmd"]
169
+
170
+ memory:
171
+ skills_dir: "~/.palapa/skills/"
172
+ db_path: "~/.palapa/sessions.db"
173
+ user_model: "~/.palapa/USER.md"
174
+ memory_md: "~/.palapa/MEMORY.md"
175
+ soul_md: "~/.palapa/SOUL.md" # persona agent, ditulis manual
176
+
177
+ audit:
178
+ enabled: false # catat semua tool call ke SQLite
179
+
180
+ api:
181
+ host: "127.0.0.1"
182
+ port: 8000
183
+
184
+ # Agent presets untuk delegation
185
+ delegation:
186
+ max_parallel: 2
187
+ agents:
188
+ network-specialist:
189
+ alias: "Budi"
190
+ model: "qwen3.6:27b"
191
+ exclusive: true # tool preset hanya via delegasi, disembunyikan dari main agent
192
+ timeout: 120
193
+ tools: [network, bash, memory]
194
+ ```
195
+
196
+ Lihat `config.yaml.example` untuk contoh lengkap.
197
+
198
+ **Inventory perangkat** tersimpan terpisah di `~/.palapa/inventory.yaml` — kelola via `palapa devices add/list` atau edit manual.
199
+
200
+ ---
201
+
202
+ ## Arsitektur
203
+
204
+ ```
205
+ AgentLoop.run(pesan)
206
+ → bangun system prompt (SOUL.md + USER.md + skills relevan + episodic hits)
207
+ → LLM call
208
+ → parse tool calls → ToolDispatcher.dispatch()
209
+ → feed hasil → ulang sampai respons final / max iterasi
210
+ → sesi tutup: persist ke episodic, jalankan Evaluator (background)
211
+ ```
212
+
213
+ | Komponen | Tanggung jawab |
214
+ |---|---|
215
+ | `agent/core.py` | ReAct loop — prompt, LLM call, dispatch tools |
216
+ | `agent/evaluator.py` | Post-session skill extractor — skor kompleksitas, tulis SKILL.md |
217
+ | `tools/` | Satu file per tool (bash, file, web_search, web_fetch, browser, memory) |
218
+ | `tools/network.py` | NetworkTool — Netmiko, bundled whitelist, whitelist_extend |
219
+ | `tools/network_whitelist.py` | BUNDLED_WHITELIST per vendor/OS |
220
+ | `mcp/` | MCP client manager (stdio + HTTP) |
221
+ | `memory/session.py` | Episodic memory — SQLite FTS5 |
222
+ | `memory/user_model.py` | Semantic memory — USER.md dan MEMORY.md |
223
+ | `memory/skills.py` | Procedural memory — folder `{slug}/SKILL.md`, dual dir, auto-migration |
224
+ | `providers/ollama.py` | OpenAI-compat adapter ke Ollama |
225
+ | `setup/` | Wizard, devices, skills installer, skills git export/import |
226
+ | `gateway/runtime.py` | Wiring collaborator bersama (`build_agent_loop`) |
227
+ | `gateway/cli.py` | Interactive REPL + `--once` scripted mode + semua subcommand |
228
+ | `gateway/api.py` | FastAPI REST API — SSE streaming, stateless |
229
+
230
+ ---
231
+
232
+ ## Testing
233
+
234
+ ```bash
235
+ uv run python -m pytest # semua test
236
+ uv run python -m pytest tests/unit/ # unit test (tidak butuh Ollama)
237
+ uv run python -m pytest tests/integration/ # integration test (butuh Ollama berjalan)
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Dokumentasi
243
+
244
+ Riset, keputusan arsitektur, eksperimen, dan progress implementasi dikelola di [palapa-wiki](https://github.com/indi9o/palapa-wiki). ADR ada di `docs/adr/`. Domain glossary ada di `CONTEXT.md`.
@@ -0,0 +1,131 @@
1
+ # PRD: Palapa — Local Autonomous AI Agent
2
+
3
+ ## Problem Statement
4
+
5
+ Existing autonomous AI agent frameworks (including Hermes Agent by NousResearch) either require cloud LLM APIs, lack full configurability, or cannot be modified without forking an upstream dependency. A developer who wants a self-improving, tool-using AI agent running entirely on local hardware — with full control over every component — has no off-the-shelf option that satisfies all three constraints simultaneously.
6
+
7
+ ## Solution
8
+
9
+ Palapa is a locally-running autonomous AI agent built from scratch, inspired by Hermes Agent's architecture but independently owned. It runs against any Ollama model via the OpenAI-compatible endpoint, uses a three-layer memory system (episodic, semantic, procedural), dispatches a core set of tools (bash, file, web, browser), and automatically extracts reusable Skills after complex tasks. It is accessible via an interactive CLI and a REST API.
10
+
11
+ ## User Stories
12
+
13
+ 1. As a developer, I want to start an interactive chat session with the agent in the terminal, so that I can give it tasks and see its tool-use steps in real time.
14
+ 2. As a developer, I want to configure the Ollama model and base URL in a single `config.yaml`, so that I can switch between models without touching code.
15
+ 3. As a developer, I want the agent to execute bash commands on my behalf, so that it can automate shell tasks without me copy-pasting commands.
16
+ 4. As a developer, I want destructive shell commands (rm, sudo, dd, etc.) to require my explicit confirmation before execution, so that the agent cannot accidentally destroy files.
17
+ 5. As a developer, I want the agent to read, write, and list files on my filesystem, so that it can work with project files directly.
18
+ 6. As a developer, I want the agent to search the web using DuckDuckGo without requiring an API key, so that it can retrieve up-to-date information.
19
+ 7. As a developer, I want the agent to fetch and parse the content of a URL, so that it can read documentation, articles, or API responses.
20
+ 8. As a developer, I want the agent to control a headless browser via Playwright, so that it can interact with JavaScript-heavy websites that plain HTTP fetch cannot handle.
21
+ 9. As a developer, I want the agent to search my past sessions by keyword, so that it can recall relevant context from previous conversations.
22
+ 10. As a developer, I want the agent to maintain a `USER.md` file about my preferences and expertise, so that it personalizes responses across sessions.
23
+ 11. As a developer, I want the agent to automatically extract a reusable Skill after completing a complex task, so that it handles similar tasks better in future sessions.
24
+ 12. As a developer, I want the Skills library to deduplicate against existing skills before writing a new one, so that the skills directory doesn't accumulate redundant files.
25
+ 13. As a developer, I want to call the agent programmatically via a REST API, so that I can integrate it into scripts and other tools.
26
+ 14. As a developer, I want the REST API to return streamed responses, so that I can display partial output as the agent works.
27
+ 15. As a developer, I want to list, read, and delete skill files via CLI commands, so that I can manage the Skills library without editing the filesystem manually.
28
+ 16. As a developer, I want each session to be summarized and persisted to a SQLite FTS5 database on close, so that episodic memory accumulates automatically.
29
+ 17. As a developer, I want the agent to load relevant skills from the Skills library at session start, so that prior learned patterns are available without explicit invocation.
30
+ 18. As a developer, I want the danger pattern list for bash confirmation to be configurable in `config.yaml`, so that I can tighten or loosen the policy to my comfort level.
31
+ 19. As a developer, I want the agent loop to have a configurable max iteration count, so that I can prevent runaway loops on complex tasks.
32
+ 20. As a developer, I want clear tool-use output in the CLI showing which tool was called and what it returned, so that I can follow the agent's reasoning step by step.
33
+
34
+ ## Implementation Decisions
35
+
36
+ - **Provider abstraction:** A `Provider` ABC wraps LLM calls. The default `OllamaProvider` uses the `openai` Python SDK with `base_url: http://10.45.185.253:11494/v1`. Swapping providers requires only a `config.yaml` change. See ADR-0001.
37
+
38
+ - **Agent Loop:** Owns both a Session's lifecycle and the ReAct-style execution of each Turn within it — one class, mirroring Hermes Agent's `AIAgent` (ADR-0006; a prior design that split this into a separate "Orchestrator" was reconsidered in favor of matching the reference architecture first, splitting later only if a concrete need appears). Per session: assembles the system prompt once at session start (config + USER.md + relevant skills + episodic memory hits) and keeps it frozen for the whole session — skill/memory updates take effect starting the next session, not mid-session (keeps the prompt prefix stable so Ollama can reuse its KV-cache across turns). Accumulates conversation history across Turns, subject to Context Compaction (below). When the session closes, persists it (`SessionStore.save()`) and invokes the Evaluator — both run in the background, not blocking the user-facing response, since both can take 80-100+ seconds. Per turn: call LLM → parse tool calls from response → dispatch via Tool Dispatcher → feed results back → repeat until LLM returns a final message with no tool calls, or max iterations reached (subject to a Grace Call, below). See ADR-0004, ADR-0006.
39
+
40
+ - **Context Compaction:** Two thresholds against `context_length`, mirroring Hermes Agent's `run_agent.py`. At >50% (preflight), and again more aggressively at >85% (safety net — Hermes runs this in a separate Gateway layer that Palapa has no equivalent of, so both thresholds live in the Agent Loop itself): older messages are compacted, the most recent N are always preserved intact, a tool-call/tool-result pair is never split apart, and anything compacted away is persisted via `SessionStore.save()` first. The exact value of N and the compression method (deterministic truncation vs. LLM summarization) are implementation details, not fixed here. See ADR-0007.
41
+
42
+ - **Grace Call:** When a Turn's `max_iterations` budget is exhausted, the loop gets exactly one more LLM call instead of a hard stop — `tools=None` (no further tool calls allowed) plus an instruction to summarize progress. Mirrors Hermes's `while (iterations < max and budget > 0) or grace_call` loop condition; the exact mechanism for forcing a summary is Palapa's own interpretation, not a confirmed detail of Hermes's implementation. See ADR-0007.
43
+
44
+ - **Tool Dispatcher:** Routes tool-call requests to registered Tool implementations. Enforces semi-restricted bash policy (ADR-0002) before executing bash tools. All tools expose a `schema()` method returning an OpenAI-compatible function definition JSON.
45
+
46
+ - **Tools (v1):**
47
+ - `BashTool` — executes shell commands; applies danger-pattern check with fail-closed confirmation timeout, a non-configurable hardline blocklist for catastrophic commands, and strips credential-like env vars (`KEY`/`TOKEN`/`SECRET`/`PASSWORD`/`CREDENTIAL`) from the child process. See ADR-0002.
48
+ - `FileTool` — read, write, list, delete local files
49
+ - `WebSearchTool` — DuckDuckGo search via `duckduckgo-search` package, no API key
50
+ - `WebFetchTool` — HTTP GET via `httpx`, returns parsed text
51
+ - `BrowserTool` — Playwright headless Chromium for JS-heavy pages
52
+ - `MemoryTool` — search episodic SQLite, read/update USER.md and MEMORY.md
53
+
54
+ - **Memory system:**
55
+ - Episodic: SQLite database with FTS5 virtual table. Schema: `(id, timestamp, summary, full_text)`. Searched at session start using keywords extracted from the user's first message.
56
+ - Semantic: `USER.md` (user model) and `MEMORY.md` (general facts). Flat markdown files, updated by MemoryTool or by Evaluator post-session. Each has a configurable character limit (`memory.user_model_char_limit` / `memory.memory_char_limit`, default 1,375 / 2,200 — matching Hermes Agent's precedent). When a file exceeds 80% of its limit, the next write triggers an LLM consolidation pass that condenses existing entries before appending.
57
+ - Procedural: `skills/` directory. Each skill is a `.md` file with YAML frontmatter (`name`, `description`, `tags`) followed by four mandatory sections: `## When to Use`, `## Procedure`, `## Pitfalls`, `## Verification`. Loaded at session start by relevance match against current task. See ADR-0005.
58
+
59
+ - **Evaluator:** Runs after each completed session. Triggers a skill write only if *both* hold: the session's tool-call count ≥ `evaluator.min_tool_calls` (default 5, a cheap structural gate checked first) *and* an LLM complexity score (1–5) ≥ `evaluator.complexity_threshold` (default 4). If triggered and no matching skill already exists (fuzzy match against existing skill descriptions), writes a new skill file. Runs fully automatically — no user confirmation. See ADR-0003, ADR-0005.
60
+
61
+ - **Config (`config.yaml`):**
62
+ ```yaml
63
+ model:
64
+ name: qwen3.6:27b
65
+ base_url: http://10.45.185.253:11494/v1
66
+ context_length: 64000
67
+ max_iterations: 90
68
+ memory:
69
+ db_path: ~/.palapa/sessions.db
70
+ user_model: ~/.palapa/USER.md
71
+ memory_md: ~/.palapa/MEMORY.md
72
+ skills_dir: ~/.palapa/skills/
73
+ user_model_char_limit: 1375
74
+ memory_char_limit: 2200
75
+ evaluator:
76
+ complexity_threshold: 4
77
+ min_tool_calls: 5
78
+ tools:
79
+ bash:
80
+ enabled: true
81
+ danger_patterns: [rm, sudo, dd, mkfs, "chmod -R", truncate, shred, "kill -9", "curl | sh", "wget | sh"]
82
+ confirmation_timeout_seconds: 60
83
+ browser:
84
+ enabled: true
85
+ headless: true
86
+ api:
87
+ host: 127.0.0.1
88
+ port: 8000
89
+ ```
90
+
91
+ - **CLI interface:** `palapa chat` starts an interactive session (one `AgentLoop` instance for the process's lifetime, accumulating history across turns) — ends on `Ctrl+D`/`Ctrl+C`, at which point the session is persisted and the Evaluator runs in the background before the process exits. `palapa skills list|show|delete` manages skills. `palapa sessions search <query>` queries episodic memory.
92
+
93
+ - **REST API:** FastAPI app, stateless — no server-side session state between requests (see ADR-0006; Palapa doesn't need Hermes's ecosystem-compatibility reasons for a stateful tier). `POST /chat` accepts `{messages: [{role, content}, ...]}` (the full conversation so far) and returns a streaming response; the server treats the whole request as one Session for persistence/Evaluator purposes, run in the background via FastAPI `BackgroundTasks` after the response is sent. `GET /skills` lists skills. `GET /health` returns model + config status.
94
+
95
+ - **Package manager:** `uv` for dependency management and virtual environment.
96
+
97
+ ## Testing Decisions
98
+
99
+ - Good tests verify external behavior: given an input message, does the agent produce the expected tool calls and/or final response? Tests must not assert on internal loop state or intermediate LLM calls.
100
+ - **OllamaProvider** is tested with a real Ollama instance running a small fast model (e.g., `llama3.2:3b`) — no mocking of LLM calls.
101
+ - **Tool unit tests:** Each Tool is tested in isolation with real filesystem/network access where possible (BashTool, FileTool), or a local mock server for WebFetchTool. BrowserTool tests use a locally served static HTML file.
102
+ - **Evaluator:** Tested by feeding it a known complex task transcript and asserting a skill file is written to a temp directory.
103
+ - **Agent Loop integration test:** Single end-to-end test: send a task that requires one tool call, assert the correct tool was dispatched and a response was returned.
104
+
105
+ ## Out of Scope
106
+
107
+ - Text-to-speech (TTS) — ElevenLabs, edge-tts, or any audio output
108
+ - Messaging gateways — Telegram, Discord, Slack, WhatsApp, Signal connectors
109
+ - Multi-user support — authentication, session isolation, user accounts
110
+ - Vector database — chromadb, qdrant, or semantic embedding search
111
+ - Image generation tools
112
+ - Code execution sandbox (Python REPL) — deferred to v2
113
+ - Subagent delegation — spawning isolated child agents for parallel/reasoning-heavy tasks (a Hermes Agent feature). No v1 user story needs it; the ReAct loop's conversation history already carries results forward within a single agent. Candidate for v2 if a real need for parallel independent workstreams emerges.
114
+
115
+ ## Post-v1 (Fase 8)
116
+
117
+ - **MCP (Model Context Protocol) client support** — not part of v1. Designed 2026-07-06 (see ADR-0008): Palapa gains a native MCP client (stdio+HTTP transports, mirroring Hermes Agent) so external MCP Servers' tools auto-register alongside built-in Tools. Client only — Palapa does not expose itself as an MCP Server. Not yet implemented.
118
+
119
+ ## Post-v1 (Fase 10)
120
+
121
+ - **Network device management** — not part of v1. Designed 2026-07-07 (see ADR-0009): a native `NetworkTool` (Netmiko-backed) lets Palapa inspect campus and IDREN network devices for a network engineer. Mikrotik only for now (Ruckus/Juniper/Cisco/Huawei deferred); read-only (config-changing commands deferred to v2). Commands are gated by a hard-coded-in-config allowlist, not an LLM-authored blocklist. Not yet implemented.
122
+
123
+ ## Further Notes
124
+
125
+ - Palapa's name derives from the Sumpah Palapa (Palapa Oath) of Gajah Mada, Mahapatih of Majapahit — a vow to complete a mission before rest. Fitting for an autonomous task-completion agent.
126
+ - The architecture deliberately mirrors Hermes Agent (NousResearch) as a reference, but all code is written independently. No Hermes source is copied.
127
+ - Ollama does not need to run on the same machine as the Palapa process — `base_url` just needs to point at wherever the server is reachable on the user's network (e.g. `http://10.45.185.253:11494/v1`, a non-default port). `OLLAMA_KEEP_ALIVE` and `OLLAMA_CONTEXT_LENGTH` are set on the Ollama server itself, not on the Palapa side.
128
+ - Ollama must be running with `OLLAMA_KEEP_ALIVE=24h` to avoid cold-start latency between agent turns.
129
+ - `context_length` in `config.yaml` is used by Palapa for its own prompt-budgeting/accounting — it does not, by itself, change the model's actual context window in Ollama. The Ollama server's context window must be raised separately via the `OLLAMA_CONTEXT_LENGTH` environment variable or a Modelfile `PARAMETER num_ctx` line; without this, the model may silently truncate context even if `config.yaml` says otherwise.
130
+ - Recommended minimum context is 64,000 tokens for reliable agent + tool-use behavior (tool schemas, skills, and memory hits all consume prompt budget before the actual task starts).
131
+ - The chosen model must support tool/function calling. Recommended: `qwen3.6:27b` (verified working against the project's dev Ollama server in Fase 2/3) or `qwen3.6:35b`. Models without tool-call support will fall back to chat-only mode with a warning.