Model or dataset
jmerelnyc/Photo-agents avatar
jmerelnyc/Photo-agents

Photo-agents: a screen-grounded agent runtime with a remote licence gate

Autonomous self-evolving agents. Vision-grounded layered memory and self-written skills for LLM agents that operate your computer.

691 stars22 forksPythonMIT

At a glance

What is it?
Photo-agents is a Python 3.10+ runtime that drives a tool-calling LLM through a perceive, reason, act loop, stores observations in layered memory, and writes its own skills. The interesting engineering is in the memory and skill layout; the friction is a remote-validated API key that gates every entry point.
Who is it for?
Adopt Photo-agents if you want a local, inspectable agent runtime whose memory and self-written skills live in files you can read at ~/.photoagents, and you accept the beta status warning that APIs may change before 1.0. Do not adopt it if the remote licence gate is a blocker, since the launcher and hub both refuse to start without a validated key.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 75 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Photo-agents targets: memory that is not a longer transcript

Most tool-calling agents carry their history as a growing chat transcript. The README states the project's position plainly: instead of dumping longer chat transcripts into a model and hoping for the best, it treats memory the way biology does, with vision in and bound observations stored in layers. That is the design bet. The agent is meant to ground in what it sees on screen rather than in what it was told earlier in the conversation.

The audience follows from that. This is for engineers who want an agent to operate a desktop: read the screen, click, type, run commands, and keep a durable record of what worked. It is not a library you import to add a chat completion helper. The package bundles a runtime, several frontends, a browser bridge, and chat-platform clients in one distribution, which tells you the intended user is someone assembling a working desktop agent rather than someone wiring a single API call into an existing service.

The repository is written in Python, licensed MIT, and marked beta. No releases have been published, so the install path is the package on PyPI plus the repository itself, not a pinned version tag.

The perceive, reason, act loop and what actually gets stored

The core is a streaming agent loop that drives any tool-calling LLM through a perceive, reason, act cycle, living under photoagents/core/ alongside the tool dispatcher. Vision enters through photoagents/web/, which the layout describes as a DOM simplifier and a Chrome DevTools Protocol driver, plus a CDP bridge under resources/tmwd_cdp_bridge/. The DOM simplifier matters more than it sounds: raw page markup is too large to hand a model every turn, so the runtime reduces the page before the model reasons over it.

Memory is layered, and the on-disk table makes the layers concrete. L2 is long-term facts in ~/.photoagents/global_mem.txt, a plain text file. L4 is raw session archives under ~/.photoagents/sessions/. L3 is SOPs and helper modules under photoagents/skills/, described as browser, vision and OCR helpers. Working memory is the in-loop layer that the README names but does not give a file path for. A vector index for skill and SOP search sits at ~/.photoagents/skill_index/, which is how the agent retrieves a previously written procedure instead of re-deriving it.

The self-evolving claim rests on photoagents/evolution/, which holds reflection and scheduler scripts. The README's own example invokes it as reflect or watchdog mode, where a check() function fires the next task. So evolution here is a scheduled reflection pass, not an online learning system. Skills are written by the agent from real success, according to the About section, and then indexed for later search. That is a closed loop only if retrieval works; the material does not describe how a bad skill gets retired.

Install, credentials, and the two files you edit before anything runs

Installation is two commands. Either pip install photoagents, or pip install "photoagents[all]" to pull every optional client and integration. Python 3.10 or newer is required, and the README says it is tested on Windows, macOS and Linux.

Two separate credential systems are involved, and conflating them is the most likely first mistake. The first is the Photo Agents API key, resolved in a fixed order: the environment variable PHOTOAGENTS_API_KEY, then the api_key field in ~/.photoagents/config.json, then an interactive prompt on first run that offers to save the value. A successful validation is cached for 24 hours. The second is your LLM provider key, which lives in credentials.py. You copy the template from the repo root with cp photoagents/config/keys_template.py credentials.py, edit it, and uncomment one provider config. A credentials.json with the same shape is also accepted.

Running it takes one of three forms. python -m photoagents gives an interactive REPL. python -m photoagents --task my_task --input "List the largest files in this directory." is one-shot file-IO mode. python -m photoagents --reflect photoagents/evolution/scheduler.py starts reflect mode. The GUI clients each have their own module path: pythonw -m photoagents.cli.launcher for the Streamlit app, pythonw -m photoagents.cli.hub for the service hub, python -m photoagents.clients.desktop_app for the PyQt desktop app, and per-platform modules under photoagents.clients for Telegram, Feishu, WeCom, DingTalk and QQ.

The provider router is configured by keyword rules in credentials.py. The README's troubleshooting entry says to check for native plus claude or oai, or mixin for the failover session. If the wrong model answers, that string matching is the first place to look.

The remote licence gate is the sharpest constraint in the design

The whole runtime is gated by a remote-validated Photo Agents API key, and the README is explicit that the launcher and hub both call the same gate before starting any service, refusing to launch anything if the key is missing or revoked. Validation is a network call to the licence endpoint, cached for 24 hours. The FAQ states the runtime talks to your configured LLM provider and the Photo Agents licence endpoint only, and that memory and skills stay local.

Read that as a trade-off rather than a flaw. Local storage of observations and skills is a real privacy property, and the README claims no screen data goes anywhere except your chosen LLM provider. But the gate means a network-reachable licence endpoint is a runtime dependency for every entry point, including the desktop app and the chat bots. If that endpoint is unreachable, the 24-hour cache buys you a day and then the gate is the question. The FAQ's answer to running fully offline is narrower than it first appears: the agent loop needs a reachable LLM provider anyway, so offline operation was never on the table, but the licence endpoint is a second dependency that has nothing to do with your model choice.

There is also no published release history. Combined with the beta status note that APIs may change before 1.0, this is software you should expect to track from main rather than pin.

Where the layered memory design gets thin

The layer model is the most interesting part of the project and also the least specified. The README names working, global, SOP and session archive layers and gives file paths for three of them, but it does not describe the promotion rule: what causes an observation to move from working memory into global_mem.txt, or how a successful action sequence becomes an L3 SOP. Without that rule, global_mem.txt is a file that grows, and the vector index under skill_index/ is only as good as what gets written into it.

Retirement is the harder gap. The README says skills are written by the agent itself from real success, and that the index supports skill and SOP search. Nothing in the material covers what happens when a skill stops working because a website changed, or how a stale SOP is demoted. For a system whose selling point is self-evolution, the absence of a documented forgetting mechanism is a real limitation, and it is the thing I would probe first in the code under photoagents/evolution/.

There is a second, more mundane failure surface. Browser tools depend on beautifulsoup4 being installed and on the CDP bridge config existing under resources/tmwd_cdp_bridge/. The README lists that as troubleshooting, which means it is a known way for the browser half of the toolset to silently not work. An agent that can run sandboxed Python, PowerShell and bash but cannot see the page is a different product from the one described in the About section.

How this differs from a general agent framework like LangChain

The obvious comparison is a general orchestration library such as LangChain. The difference is not the model routing, which both do, but where state lives and who owns it. LangChain's memory abstractions are typically backed by a store you configure, often a database or a hosted service, and its tools are functions you register. Photo-agents ships an opinionated on-disk layout instead: global_mem.txt for facts, sessions/ for archives, skill_index/ for retrieval, temp/ for per-task scratch. You can read the agent's memory with a text editor and back it up by copying a directory.

That choice has costs. A flat text file for L2 facts does not give you concurrent writers, schema migration, or query beyond whatever the runtime implements. A database-backed memory store handles those cases and Photo-agents does not. What you get in exchange is inspectability: when the agent does something surprising, the evidence is in ~/.photoagents rather than behind an API.

The second difference is the skill model. In a tool-registration framework, the set of capabilities is fixed by the developer at build time. Here the agent writes its own SOPs into photoagents/skills/ and indexes them for search. That is a genuinely different posture, and it is also the part of the design with the least documentation about failure.

On observability, the project takes the integration route rather than building its own: optional Langfuse hooks live under photoagents/integrations/, and there is a cron-style scheduler. So it is not a full replacement for a tracing stack, it is a client of one.

Maintenance cost, licence terms, and what to check before adopting

The licence is MIT, which permissive terms permit commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is the standard MIT grant and it applies to the code in this repository. It does not settle the separate question of the Photo Agents API key: the gate is a service, and the terms governing that service are not in the README or the LICENSE file. If your use case depends on the gate staying available on your schedule, that is a question for the maintainers, not a question the MIT text answers. This is not legal advice; read the LICENSE and whatever governs the key endpoint yourself.

Maintenance cost is shaped by two facts. There are no releases, so upgrades mean pulling main and reconciling against a beta API that the README says may change before 1.0. And the runtime has a wide optional surface: pip install "photoagents[all]" pulls every client and integration, which is more dependency surface than a terminal-only user needs. Installing the base package and adding clients individually keeps that narrower.

The verification order I would use: confirm PHOTOAGENTS_API_KEY validates and that the cached result survives a restart, confirm credentials.py routes to the intended provider by checking the native plus claude or oai keyword rules, then exercise the browser path specifically, since it is the one the README flags as fragile. If the browser tools are the reason you are here, test them before you build anything on top.

Editorial conclusion

Adopt Photo-agents if you want a local, inspectable agent runtime whose memory and self-written skills live in files you can read at ~/.photoagents, and you accept the beta status warning that APIs may change before 1.0. Do not adopt it if the remote licence gate is a blocker, since the launcher and hub both refuse to start without a validated key. Before committing, verify three things: that PHOTOAGENTS_API_KEY validation succeeds against the licence endpoint, that beautifulsoup4 plus resources/tmwd_cdp_bridge/ actually drive your browser, and that the keyword rules in credentials.py resolve to the provider you expect.

Official sources

  1. Issues
  2. jmerelnyc/Photo-agents on GitHub
  3. License: MIT
  4. README
Community notes

Community notes