KHarness
A lightweight Python framework for building LLM agents with tool use, conversation memory, and multi-round research pipelines. Supports local inference via llama.cpp and Ollama.
Installation
pip install kharness
Optional dependencies (install what you need):
pip install langchain-core # Required for tool decorators
pip install ddgs beautifulsoup4 # Web tools
pip install yahoors # Stock tools
Providers
Providers wrap a local inference backend and expose a unified chat() interface.
Ollama
from kharness.providers import Ollama
provider = Ollama("qwen2.5:7b") # model is required
response = provider.chat(
[{"role": "user", "content": "Hello!"}]
)
| Parameter | Default | Description |
|---|---|---|
model |
— | Model name (required) |
server_url |
"http://localhost" |
Server host |
port |
"11434" |
Server port |
max_iterations |
10 |
Max tool-call loop iterations |
LlamaCpp
Assumes a llama-server process is already running. Connect to it:
from kharness.providers import LlamaCpp
provider = LlamaCpp() # defaults: 127.0.0.1:8080
if provider.check_health():
response = provider.chat(
[{"role": "user", "content": "Hello!"}]
)
| Parameter | Default | Description |
|---|---|---|
server_url |
"http://127.0.0.1" |
Server host |
port |
"8080" |
Server port |
max_iterations |
5 |
Max tool-call loop iterations |
strip_tools_after |
3 |
Force text response after N tool rounds |
Agent
Agent wraps a provider with optional tools and memory, exposing run() for chat and research() for multi-round deep dives.
Basic chat
from kharness.providers import Ollama
from kharness.agent import Agent
provider = Ollama("qwen2.5:7b")
agent = Agent(provider)
response = agent.run("What is the capital of France?")
print(response)
With a system prompt file
agent = Agent(provider, soul_md_path="persona.md")
With tools
Pass a dict or list of dicts mapping tool names to LangChain @tool objects:
from kharness.tools import WEB_TOOL_MAP
agent = Agent(provider, tool_map=WEB_TOOL_MAP)
response = agent.run("What happened in the news today?")
With memory
Attach a Memory object to maintain conversation history across turns:
from kharness.memory import Memory
memory = Memory(max_turns=20)
agent = Agent(provider, memory=memory)
agent.run("My name is Alice.")
agent.run("What's my name?") # remembers "Alice"
Memory
Memory manages a sliding window of conversation history. It stores messages as {"role": ..., "content": ...} dicts — the format all providers expect.
from kharness.memory import Memory
memory = Memory(max_turns=10) # keeps last 10 user/assistant pairs
memory.add("user", "Hello")
memory.add("assistant", "Hi there!")
history = memory.get_history() # list of message dicts
memory.clear()
| Parameter | Default | Description |
|---|---|---|
max_turns |
20 |
Max user/assistant pairs to retain |
Research pipeline
agent.research() runs a structured multi-round research loop:
- Plan — generates search queries from the question
- Gather — runs web searches for each query
- Analyze — synthesizes findings and decides if more searching is needed
- Repeat — loops up to
max_roundstimes if gaps remain - Report — writes a final comprehensive answer
from kharness.providers import Ollama
from kharness.tools import WEB_TOOL_MAP
from kharness.agent import Agent
provider = Ollama("qwen2.5:14b")
agent = Agent(provider, tool_map=WEB_TOOL_MAP)
report = agent.research(
"What are the latest developments in fusion energy?",
max_rounds=3,
planning_tokens=512,
analysis_tokens=2048,
report_tokens=8000,
)
print(report)
| Parameter | Default | Description |
|---|---|---|
max_rounds |
3 |
Maximum search/analyze iterations |
planning_tokens |
1024 |
Token budget for query planning |
analysis_tokens |
2048 |
Token budget for per-round analysis |
report_tokens |
8000 |
Token budget for final report |
debug |
True |
Log phase progress |
Tools
Tools are standard LangChain @tool functions. Convenience maps are exported for easy use with Agent.
Web tools
from kharness.tools import WEB_TOOL_MAP
| Tool | Description |
|---|---|
web_search |
DuckDuckGo text search, returns top snippets |
fetch_page |
Fetches a URL and extracts readable text |
news_search |
DuckDuckGo news search with dates |
image_search |
Returns direct image URLs |
wikipedia_summary |
Wikimedia REST API summary |
search_and_fetch |
Combines search + full page fetch |
search_subreddit |
Fetches top posts from a subreddit |
Stock tools
from kharness.tools import STOCK_TOOL_MAP
| Tool | Description |
|---|---|
get_candles |
OHLCV candlestick data |
get_options |
Options chain (calls and puts) |
get_income_statements |
Income statement financials |
get_balance_sheet |
Balance sheet financials |
get_cash_flow |
Cash flow statement |
Custom tools
Any LangChain @tool works:
from langchain_core.tools import tool
@tool
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
agent = Agent(provider, tool_map={"add": add})
Logging
KHarness uses Python's standard logging module. To see runtime output:
import logging
logging.basicConfig(level=logging.INFO)
Use logging.DEBUG to see individual tool calls.
Requirements
- Python >= 3.12
- A running Ollama daemon or llama-server process
Metadata
Release files for kharness 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kharness-0.1.1.tar.gz | 14.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kharness-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.8 kB
Release files / kharness-0.1.1.tar.gz
| Download URL | kharness-0.1.1.tar.gz |
|---|---|
| Size | 14.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c1e49171f486f22e74de846a21eaea557acdb037f8de2f0a2c105dcf6ea2b07
|
|
BLAKE2b-256 checksum How to use checksums |
1dca658ad538d90415948ceda113afbf6b40436e970104a92ffee7c47cc274b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / kharness-0.1.1-py3-none-any.whl
| Download URL | kharness-0.1.1-py3-none-any.whl |
|---|---|
| Size | 15.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cc8cc7a8f6b0a263bd93fea5d0022ad56bc2c28fa369b6b945f41f982201f4dc
|
|
BLAKE2b-256 checksum How to use checksums |
19ecc4501b542b88c819d0307cc113aa48738c1bb543cb403ed13ae94dbe4236
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|