From eb23658610d48c6f8b4b9065a39bcacebca04d08 Mon Sep 17 00:00:00 2001 From: Gautier Delache Date: Mon, 26 Oct 2026 15:04:14 +0100 Subject: [PATCH 1/2] docs: rewrite README and add CONTRIBUTING for the current Forest positioning Pitch for regulated ops teams, real quick start, architecture diagram (light/dark SVG generated from the brand toolchain), and links to docs.forest.app. Drops the Discourse badge and community section: community.forestadmin.com is being sunset and redirected to forest.app/forms/support. Co-Authored-By: Claude Opus 5.5 (1M context) --- CONTRIBUTING.md | 57 ++++++++ README.md | 209 +++++++++++++-------------- assets/arch-agent-python-dark.svg | 1 + assets/arch-agent-python-light.svg | 1 + assets/header-agent-python-dark.svg | 7 + assets/header-agent-python-light.svg | 7 + 6 files changed, 172 insertions(+), 110 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 assets/arch-agent-python-dark.svg create mode 100644 assets/arch-agent-python-light.svg create mode 100644 assets/header-agent-python-dark.svg create mode 100644 assets/header-agent-python-light.svg diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..32bbad8b8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# Contributing to agent-python + +Thanks for helping improve the Forest Python agent. This guide covers how to report an issue, set up the repository, and get a pull request merged. + +## Before you start + +- **Found a bug?** Open an issue: expected behavior, actual behavior, logs, and the package versions you use (Django or Flask included). +- **Found a security issue?** Do not open a public issue. Follow the [security policy](https://github.com/ForestAdmin/.github/blob/main/SECURITY.md). +- **Planning a large change?** Open an issue first to discuss it, so your work fits the agent's direction before you write it. + +## Setup + +This monorepo holds one package per folder in [`src/`](./src), managed with Poetry. Python `>=3.8,<3.14` is supported. + +```bash +pip install -r requirements.txt # installs pre-commit +pre-commit install +``` + +Demo applications for Django and Flask live in [`src/_example/`](./src/_example). + +## Tests + +Run the whole suite the way the CI does: + +```bash +./launch_tests_ci_like.sh +``` + +Or one package at a time: + +```bash +cd src/ +poetry install --with=test +poetry run coverage run -m pytest +``` + +Tests must pass and the pre-commit hooks must be clean before you open a pull request. + +## Commit messages + +Commits follow the [Conventional Commits](https://www.conventionalcommits.org/) specification. Releases and changelogs are generated from them by semantic-release, so the type matters: + +- `fix(django_agent): handle null dates` → patch release +- `feat(datasource_sqlalchemy): add the X option` → minor release +- `docs: ...`, `test: ...`, `chore: ...` → no release + +## Pull requests + +1. Fork the repository and create a branch from `main`. +2. Make your change, with tests. +3. Give the pull request a Conventional Commits title. +4. The CI must be green. The Forest team reviews every pull request before merging. + +## Code of conduct + +Everyone taking part in this project is expected to follow the [code of conduct](https://github.com/ForestAdmin/.github/blob/main/CODE_OF_CONDUCT.md). diff --git a/README.md b/README.md index 92e36c8ae..9d46ee05d 100644 --- a/README.md +++ b/README.md @@ -1,145 +1,134 @@ -# agent-python - -## In a nutshell - -Forest Admin provides an off-the-shelf administration panel based on a highly-extensible API plugged into your application. - -This project has been designed with scalability in mind to fit requirements from small projects to mature companies. - -## Who Uses Forest Admin - -- [Apartmentlist](https://www.apartmentlist.com) -- [Carbon Health](https://carbonhealth.com) -- [Ebanx](https://www.ebanx.com) -- [First circle](https://www.firstcircle.ph) -- [Forest Admin](https://www.forestadmin.com) of course :-) -- [Heetch](https://www.heetch.com) -- [Swile](https://www.swile.co) -- [Pillow](https://www.pillow.com) -- [Qonto](https://www.qonto.eu) -- [Shadow](https://shadow.tech) -- And hundreds more… - -## Getting Started - -[https://docs.forestadmin.com/documentation/how-tos/setup/install](https://docs.forestadmin.com/documentation/how-tos/setup/install) - -## Documentation - -[https://docs.forestadmin.com/developer-guide-agents-python](https://docs.forestadmin.com/developer-guide-agents-python) - -## How it works - -

- Howitworks +

+ + + Forest agent for Python: Django and Flask, your data and workflows running on your infrastructure. +

-Forest Admin consists of two components: - -- The Admin Frontend is the user interface where you'll manage your data and configuration. -- The Admin Backend API hosted on your servers where you can find and extend your data models and all the business logic (routes, actions, …) related to your admin panel. - -The Forest Admin gem (aka Forest Liana) introspects all your data model -and dynamically generates the Admin API hosted on your servers. The Forest Admin -interface is a web application that handles communication between the admin -user and your application data through the Admin API. - -## Features - -### CRUD - -All of your CRUD operations are natively supported. The API automatically -supports your data models' validation and allows you to easily extend or -override any API routes' with your very own custom logic. - -CRUD - -### Search & Filters - -Forest Admin has a built-in search allowing you to run basic queries to -retrieve your application's data. Set advanced filters based on fields and -relationships to handle complex search use cases. - -Search and Filters +

+ PyPI Django + PyPI Flask + CI + License +

-### Sorting & Pagination +**Forest is the back office for operations teams in regulated companies.** Ops teams review, decide and act on your data from one interface, or let AI agents do it, within the roles, permissions and audit logs you define. -Sorting and pagination features are natively handled by the Admin API. We're -continuously optimizing how queries are run in order to display results faster -and reduce the load of your servers. +This repository is the **Python agent** for **Django** and **Flask**: the part of Forest that runs inside your application, connects to your databases, and exposes them to the Forest interface. Your business data never goes through Forest. -Sorting and Pagination +> [!NOTE] +> **Forest v2.** This is the current Python SDK. Using `django-forestadmin`? You are on v1: see the [migration guide](https://docs.forest.app/guides/migration/from-v1/overview). -### Custom action +## Quick start -A custom action is a button which allows you to trigger an API call to execute -a custom logic. With virtually no limitations, you can extend the way you -manipulate data and trigger actions (e.g. refund a customer, apply a coupon, -ban a user, etc.) +### Django -Custom action +```bash +pip install forestadmin-agent-django +``` -### Export +The agent plugs in through your settings, not a constructor: -Sometimes you need to export your data to a good old fashioned CSV. Yes, we -know this can come in handy sometimes :-) +```python +# settings.py +INSTALLED_APPS = [ + # ... + "forestadmin.django_agent", +] -Export +FOREST_AUTH_SECRET = os.environ.get("FOREST_AUTH_SECRET") +FOREST_ENV_SECRET = os.environ.get("FOREST_ENV_SECRET") +FOREST_CUSTOMIZE_FUNCTION = "app.forest_admin.customize_forest" +``` -### Segments +```python +# urls.py +urlpatterns = [ + path("", include("forestadmin.django_agent.urls")), +] +``` -Get in app access to a subset of your application data by doing a basic search -or typing an SQL query or implementing an API route. +### Flask + SQLAlchemy -Segments +```bash +pip install forestadmin-agent-flask forestadmin-datasource-sqlalchemy +``` -### Dashboards +```python +from flask import Flask +from forestadmin.datasource_sqlalchemy.datasource import SqlAlchemyDatasource +from forestadmin.flask_agent.agent import create_agent -Forest Admin is able to tap into your actual data to chart out your metrics -using a simple UI panel, a SQL query or a custom API call. +def create_app(): + app = Flask(__name__) + agent = create_agent(app) + with app.app_context(): + db.init_app(app) + agent.add_datasource(SqlAlchemyDatasource(db)) + agent.start() + return app +``` -Dashboard +Full guide: [docs.forest.app/get-started/quickstart](https://docs.forest.app/get-started/quickstart) -### WYSIWYG +## Requirements -The WYSIWYG interface saves you a tremendous amount of frontend development -time using drag'n'drop as well as advanced widgets to build customizable views. +| | | +|---|---| +| Python | `>=3.8,<3.14` (CI tests 3.8 to 3.13) | +| Django | `>=3.2,<5.2` | +| Flask | `>=2.0.0` (`async` extra) | +| SQLAlchemy | `>=1.4.0` | -WYSIWYG +## What the agent gives you -### Custom HTML/JS/CSS +| | | +|---|---| +| **Data** | Your Django models or SQLAlchemy tables, introspected and exposed to Forest. | +| **Customization** | Computed fields, actions, segments and hooks in Python, from your customize function. | +| **Permissions and audit** | Roles, scopes and activity logs defined in Forest, enforced on every request. | -Code your own views using JS, HTML, and CSS to display your application data in -a more appropriate way (e.g. Kanban, Map, Calendar, Gallery, etc.). +## How it works -Custom views + + + The Python agent runs on your infrastructure. Forest calls it over HTTPS; the agent queries your databases and services. + -### Team-based permissions +The agent runs **on your infrastructure**. The Forest interface calls your agent, and your agent queries your sources: Forest does not store your business data. -Without any lines of code, manage directly from the UI who has access or can -act on which data using a team-based permission system. +## Documentation -Team based permissions +| | | +|---|---| +| Get started | https://docs.forest.app/get-started/quickstart | +| Connect a data source | https://docs.forest.app/get-started/connect/data-sources/overview | +| Migrating from v1 | https://docs.forest.app/guides/migration/from-v1/overview | -### Third-party integrations +
+Packages in this monorepo -Leverage data from third-party services by reconciling it with your -application’s data and providing it directly to your Admin Panel. All your -actions can be performed at the same place, bringing additional intelligence to -your Admin Panel and ensuring consistency. +| PyPI package | Role | +|---|---| +| `forestadmin-agent-django` | Agent for Django | +| `forestadmin-agent-flask` | Agent for Flask | +| `forestadmin-agent-toolkit` | Agent core (transport, auth, permissions) | +| `forestadmin-datasource-toolkit` | Data source contracts, queries, types | +| `forestadmin-datasource-django` | Django ORM data source | +| `forestadmin-datasource-sqlalchemy` | SQLAlchemy data source | -Third-party integrations +All packages install into the shared `forestadmin.*` namespace. Complete demo applications live in [`src/_example/`](./src/_example). -### Notes & Comments +
-Assign your teammates to specific tasks, leave a note or simply comment a -record, thereby simplifying collaboration all across your organization. +## Contributing -Notes and Comments +Bug reports and pull requests are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, tests and commit conventions. -### Activity logs +```bash +./launch_tests_ci_like.sh # runs the CI locally +``` -Monitor each action executed and follow the trail of modification on any data -with an extensive activity log system. +## License -Activity logs +Apache 2.0. See [LICENSE](./LICENSE). diff --git a/assets/arch-agent-python-dark.svg b/assets/arch-agent-python-dark.svg new file mode 100644 index 000000000..a805d959d --- /dev/null +++ b/assets/arch-agent-python-dark.svg @@ -0,0 +1 @@ + diff --git a/assets/arch-agent-python-light.svg b/assets/arch-agent-python-light.svg new file mode 100644 index 000000000..76073ec30 --- /dev/null +++ b/assets/arch-agent-python-light.svg @@ -0,0 +1 @@ + diff --git a/assets/header-agent-python-dark.svg b/assets/header-agent-python-dark.svg new file mode 100644 index 000000000..76bbd544e --- /dev/null +++ b/assets/header-agent-python-dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/header-agent-python-light.svg b/assets/header-agent-python-light.svg new file mode 100644 index 000000000..4d07a6cc8 --- /dev/null +++ b/assets/header-agent-python-light.svg @@ -0,0 +1,7 @@ + + + + + + + From 31fe72b261c0ea597b3d9f88d53587dcd8895e10 Mon Sep 17 00:00:00 2001 From: Gautier Delache Date: Mon, 26 Oct 2026 15:45:04 +0100 Subject: [PATCH 2/2] docs: make the Django and Flask quick starts run as written Drop FOREST_CUSTOMIZE_FUNCTION from the minimal Django setup (a missing module stops the agent) and explain it below; add the missing imports. Flask: load the secrets into app.config, which is the only place FlaskAgent reads them, and define db with flask-sqlalchemy. Co-Authored-By: Claude Opus 5.5 (1M context) --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d46ee05d..32f313ac0 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ The agent plugs in through your settings, not a constructor: ```python # settings.py +import os + INSTALLED_APPS = [ # ... "forestadmin.django_agent", @@ -38,29 +40,42 @@ INSTALLED_APPS = [ FOREST_AUTH_SECRET = os.environ.get("FOREST_AUTH_SECRET") FOREST_ENV_SECRET = os.environ.get("FOREST_ENV_SECRET") -FOREST_CUSTOMIZE_FUNCTION = "app.forest_admin.customize_forest" ``` ```python # urls.py +from django.urls import include, path + urlpatterns = [ path("", include("forestadmin.django_agent.urls")), ] ``` +Your Django models are exposed automatically. To add computed fields, actions or segments, point `FOREST_CUSTOMIZE_FUNCTION` to a function that receives the agent (e.g. `"myapp.forest_admin.customize_forest"`). The module must exist: if it cannot be imported, the agent does not start. + ### Flask + SQLAlchemy ```bash -pip install forestadmin-agent-flask forestadmin-datasource-sqlalchemy +pip install forestadmin-agent-flask forestadmin-datasource-sqlalchemy flask-sqlalchemy ``` ```python +import os + from flask import Flask +from flask_sqlalchemy import SQLAlchemy from forestadmin.datasource_sqlalchemy.datasource import SqlAlchemyDatasource from forestadmin.flask_agent.agent import create_agent +db = SQLAlchemy() # your models are declared on this instance + def create_app(): app = Flask(__name__) + app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"] + # the agent reads its settings from app.config, not from the environment + app.config["FOREST_ENV_SECRET"] = os.environ["FOREST_ENV_SECRET"] + app.config["FOREST_AUTH_SECRET"] = os.environ["FOREST_AUTH_SECRET"] + agent = create_agent(app) with app.app_context(): db.init_app(app)