Skip to main content

Agent execution history middleware for Autourgos — logs every thought, tool call, and observation to Markdown and JSON files with automatic sensitive-data redaction

Project description

autourgos-history

Agent execution history middleware for the Autourgos framework.

Attach it to any Autourgos agent and every run is automatically recorded: every Thought, every Tool Call, every Observation, and the Final Answer — written to a Markdown file and a structured JSON file.

Sensitive values (API keys, tokens, passwords) are automatically redacted before writing.

Zero required dependencies. Pure Python 3.10+.


Why use this?

When you build agents, you need to know what they did. This middleware gives you a complete, readable audit trail of every agent run without adding any code to your agent logic.

  • Debug — see exactly where the agent went wrong
  • Audit — keep records of every tool call and its inputs
  • Monitor — review agent reasoning in plain English
  • Privacy — choose exactly what gets logged with per-field flags

Table of Contents


Install

pip install autourgos-history

Requires Python 3.10+. No other dependencies.


Quick Start

from autourgos_history     import AgentHistoryMiddleware
from autourgos_react_agent import ReactAgent
from autourgos_openaichat  import OpenAIChatModel

history = AgentHistoryMiddleware(
    include_query=True,
    include_tools=True,
    include_observations=True,
    include_final=True,
)

agent = ReactAgent(
    llm=OpenAIChatModel(model="gpt-4o"),
    middleware=[history],
)
agent.add_tools(my_tool)

result = agent.invoke("What is the weather in Tokyo?")
print(result)
# The weather in Tokyo is 22°C and sunny.

After the run, two files appear in ./Agent History/:

Agent History/
├── Task_20260616_120000_abc12345.md    ← human-readable Markdown
└── Task_20260616_120000_abc12345.json  ← structured JSON

Output Files

Markdown file (.md)

Human-readable. Open in any editor or Markdown viewer.

# Task Session: ReactAgent
**Started At:** 2026-06-16 12:00:00

## Initial Query
What is the weather in Tokyo?

---

## Iteration 1

### Thought
I need to call the get_weather tool to find the weather in Tokyo.

### Action (Tools)
**Tool:** `get_weather`
**Parameters:**
```json
{
  "city": "Tokyo",
  "unit": "celsius"
}

Observations

get_weather: "The weather in Tokyo is 22°C and sunny."


Final Answer

The weather in Tokyo is 22°C and sunny.


### JSON file (`.json`)

Structured. Use for programmatic processing, dashboards, or storage.

```json
{
  "query": "What is the weather in Tokyo?",
  "agent_name": "ReactAgent",
  "start_time": "2026-06-16T12:00:00.123456",
  "end_time":   "2026-06-16T12:00:02.456789",
  "iterations": [
    {
      "iteration": 1,
      "thought": "I need to call the get_weather tool...",
      "tools": [
        {"tool": "get_weather", "params": {"city": "Tokyo", "unit": "celsius"}}
      ],
      "observations": [
        {"tool": "get_weather", "result": "The weather in Tokyo is 22°C and sunny."}
      ]
    }
  ],
  "final_response": "The weather in Tokyo is 22°C and sunny.",
  "error": null
}

Privacy Controls

By default, content is redacted — you see the structure but not the values. Enable fields individually:

history = AgentHistoryMiddleware(
    include_query=False,        # user query    → [REDACTED: length=32]
    include_tools=True,         # tool params   → written as JSON
    include_observations=True,  # tool results  → written as JSON
    include_final=True,         # final answer  → written as text
)
Flag Default Controls
include_query False Whether the user's query is written or replaced with [REDACTED: length=N]
include_tools True Whether tool parameters are written or replaced with [REDACTED]
include_observations True Whether tool results (observations) are written or replaced with [REDACTED]
include_final True Whether the final answer is written or replaced with [REDACTED]

Even with all flags set to True, automatic redaction still applies to sensitive keys and values. See Redaction Rules.


Custom File Location

Save to a specific folder

history = AgentHistoryMiddleware(folder="/var/log/agents")
# writes: /var/log/agents/Task_20260616_120000_abc12345.md
#         /var/log/agents/Task_20260616_120000_abc12345.json

Save with a specific filename

history = AgentHistoryMiddleware(file_path="run_001.md")
# writes: ./run_001.md
#         ./run_001.json

Combine folder + filename

history = AgentHistoryMiddleware(
    folder="/var/log/agents",
    file_path="my_task.md",
)
# writes: /var/log/agents/my_task.md
#         /var/log/agents/my_task.json

Default (no arguments)

Files are auto-named and saved to ./Agent History/ in your working directory.


Using with ReactAgent

from autourgos_history     import AgentHistoryMiddleware
from autourgos_react_agent import ReactAgent
from autourgos_openaichat  import OpenAIChatModel

def search(query: str) -> str:
    return f"Search results for: {query}"

search_tool = {
    "name": "search",
    "description": "Search the web.",
    "parameters": {
        "type": "object",
        "properties": {
            "query": {"type": "string", "description": "Search terms"}
        },
        "required": ["query"],
    },
    "func": search,
}

history = AgentHistoryMiddleware(
    include_query=True,
    include_tools=True,
    include_observations=True,
    include_final=True,
)

agent = ReactAgent(
    llm=OpenAIChatModel(model="gpt-4o"),
    middleware=[history],
)
agent.add_tools(search_tool)

result = agent.invoke("Find the latest Python release notes.")
print(result)

# history.flush() — optional, ensures files are fully written before process exits

Using with Any Agent

AgentHistoryMiddleware is a CallbackHandler. Any agent that accepts middleware / callback handlers will work.

Add it at construction time:

agent = MyAgent(llm=llm, middleware=[AgentHistoryMiddleware()])

Or after construction:

agent.add_middleware(AgentHistoryMiddleware())

The middleware listens for these lifecycle events fired by the agent:

Event When it fires
on_agent_start Agent receives a new query
on_iteration_start New Thought → Action → Observe cycle begins
on_llm_end LLM returns its raw response
on_tool_start Tool is about to be called
on_tool_end Tool returned a result
on_tool_error Tool raised an exception
on_agent_end Agent produced a final answer
on_agent_error Agent raised an unhandled exception

Flushing Logs

File I/O is async (dispatched to a background thread). If your process might exit immediately after invoke(), call flush() to wait for all writes to complete:

result = agent.invoke("My task")
history.flush()  # wait for files to finish writing

This is rarely needed in long-running applications but important in scripts and tests.


Constructor Reference

Parameter Type Default Description
file_path str None Exact path for the Markdown file. JSON file uses the same name with .json extension
folder str None Directory for auto-named files. Defaults to ./Agent History/
include_query bool False Write the user's query to the log
include_tools bool True Write tool parameters to the log
include_observations bool True Write tool results (observations) to the log
include_final bool True Write the final answer to the log

Markdown Output Format

# Task Session: <AgentName>
**Started At:** YYYY-MM-DD HH:MM:SS

## Initial Query
<query or [REDACTED: length=N]>

---

## Iteration 1

### Thought
<LLM reasoning>

### Action (Tools)
**Tool:** `tool_name`
**Parameters:**
```json
{ ... }

Observations

tool_name: <result or [REDACTED]>


Final Answer

<answer or [REDACTED]>


---

## JSON Output Format

```json
{
  "query":          "string | null",
  "agent_name":     "string",
  "start_time":     "ISO 8601 datetime",
  "end_time":       "ISO 8601 datetime",
  "iterations": [
    {
      "iteration":    1,
      "thought":      "string | null",
      "tools": [
        {"tool": "tool_name", "params": { ... }}
      ],
      "observations": [
        {"tool": "tool_name", "result": "string"}
      ]
    }
  ],
  "final_response": "string | null",
  "error":          "string | null"
}

Redaction Rules

Applied automatically before any write, regardless of include_* flags.

By key name

Keys matching this pattern (case-insensitive) have their value replaced with [REDACTED]:

api_key, api-key, token, secret, password,
authorization, cookie, session, credential

Example:

{"api_key": "sk-abc123"}    {"api_key": "[REDACTED]"}

By value shape

Values that look like secrets are replaced regardless of key name:

Pattern Example
sk-... OpenAI API keys
AKIA... AWS access keys
Bearer ... HTTP authorization headers
ghp_... GitHub personal access tokens
ya29.... Google OAuth tokens

By length

String values longer than 512 characters are truncated:

"very long text..." → "first 512 chars... [TRUNCATED]"

Thread Safety

Each concurrent agent call gets its own thread-local state — query, iteration data, file paths, and the logger are all isolated per thread. Multiple agents can run concurrently with the same AgentHistoryMiddleware instance and their logs will never mix.

All disk writes are dispatched to a single-worker background executor per middleware instance, keeping agent execution fast and preventing file corruption from concurrent writes.


License

MIT — Copyright (c) 2026 Jitin Kumar Sengar

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autourgos_history-1.0.0.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autourgos_history-1.0.0-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file autourgos_history-1.0.0.tar.gz.

File metadata

  • Download URL: autourgos_history-1.0.0.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for autourgos_history-1.0.0.tar.gz
Algorithm Hash digest
SHA256 cf42bb343580fd751bfabb69509a170b8c19804dc37e8e6c164f56d9df69c019
MD5 16df7b57a16173de73b3a451bedac4e6
BLAKE2b-256 e60f32f747e38055f72099a99b5ed0278efcdc49c6b1fdc86c51129e48b1a9cc

See more details on using hashes here.

File details

Details for the file autourgos_history-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for autourgos_history-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e93d859cb46937a005db689427f6f2b417445604c9f4f4a70cfa8e1bdcf171be
MD5 f73658591e9ee010db4c897db80571d5
BLAKE2b-256 3dd768e42772fd28497b273d99080dcbb16ee1f09674f469a5b3c8c8bfa88af3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page