Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/java/org/ecocean/api/AgentSkill.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class AgentSkill extends ApiBase {
m.put("find-misfiled-sightings", "find-misfiled-sightings.md");
m.put("how-good-is-our-matching", "how-good-is-our-matching.md");
m.put("review-id-problems", "review-id-problems.md");
m.put("inat-to-wildbook-import", "inat-to-wildbook-import.md");
SKILL_RESOURCES = Collections.unmodifiableMap(m);
}

Expand Down
66 changes: 66 additions & 0 deletions src/main/resources/agent-skills/inat-to-wildbook-import.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
name: inat-to-wildbook-import
description: Pull recent iNaturalist sightings of your species, curate them, and prepare them for bulk import into Wildbook.
---

# Get iNaturalist sightings into Wildbook

## When to use this
Use this when the person says things like "get recent iNaturalist observations of my species
ready for Wildbook", "pull last month's jaguar sightings from the Pantanal so I can import them",
or "download weedy seadragon photos from iNaturalist for our catalog."

## What it does, in plain terms
It downloads recent, wild, photographed sightings of the species you name from iNaturalist, keeps
only the ones suitable for photo identification, downloads the photos, and writes a Wildbook
bulk-import spreadsheet plus a folder of photos. It can also make a simple web page for reviewing
the sightings and unchecking any you don't want before import. It only prepares files — you do the
actual import in Wildbook, and you decide what to keep.

## What you'll need
Python 3.6 or newer (standard library only; the Pillow package is needed only if you want animated
GIFs handled). The species name(s), and optionally a place and a number of days back. The Wildbook
`locationID` and `submitterID` you want stamped on the encounters. No iNaturalist account and no
Wildbook token are required — this uses the public iNaturalist API and hands the finished files to
Wildbook's Bulk Import page.

## Where the tool lives
The tool is the public, MIT-licensed repository
`https://github.com/WildMeOrg/inat-download-recent-species-sightings`, pinned to release `v1.0.0`.
Fetch that release — either download `inat-download-new-species-sightings.py` from the `v1.0.0`
tag, or clone the repo and check out `v1.0.0`. Always use the pinned release so results stay
consistent.

## How to do it
1. Get the tool at the pinned release:
`git clone https://github.com/WildMeOrg/inat-download-recent-species-sightings && cd inat-download-recent-species-sightings && git checkout v1.0.0`
(or download `inat-download-new-species-sightings.py` from the `v1.0.0` tag).
2. Run it for the person's species and scope. Example:
`python3 inat-download-new-species-sightings.py --species "Panthera onca" --days 30 --place "Mato Grosso" --use-locationID "MatoGrosso" --use-submitterID "their_wildbook_username" --html-review --output ./inat_data`
Use `--social-split-observations` for social species where several animals can share one
observation. Drop `--html-review` to write the CSV directly with no review page.
3. If you made the review page, open it and help the person uncheck low-quality or unlicensed
sightings; the page keeps good ones checked and sorted to the top. Export the curated CSV.
4. Hand off for import: tell the person to open Wildbook's **Bulk Import** page, upload the
`photos/` folder, then upload the CSV. Every row is marked `unapproved` so their team verifies
before anything enters analyses.
5. Each row carries `Encounter.otherCatalogNumbers` set to `iNaturalist:<observation id>`. This is
the back-reference that lets Wildbook recognise a sighting that was already imported, so keep it
in the spreadsheet.

## How to report results
Speak plainly. Say, for example, "I found 47 jaguar sightings from the Pantanal in the last 30
days; 39 have open licenses and clear photos and are ready to import." Tell the person where the
CSV and `photos/` folder are, how many rows the spreadsheet has, and the exact next step (upload
the photos then the CSV on Wildbook's Bulk Import page). Never say anything was imported — you only
prepared the files.

## Cautions
Respect iNaturalist licenses: sightings whose photos have no open license are flagged and left
unchecked — do not import them without the owner's permission. The tool is polite to iNaturalist's
servers (about one request per second); large pulls take a few minutes. Everything is stamped
`unapproved` for the team's own review. This skill cannot import for you and cannot change anything
in Wildbook — the person does the upload.

## Additional references
- Tool source (MIT): https://github.com/WildMeOrg/inat-download-recent-species-sightings (release `v1.0.0`)
33 changes: 22 additions & 11 deletions src/main/resources/agent-skills/index.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# Wildbook Catalog Helper — Toolbox
# Wildbook Helper — Toolbox

These tools help you check and tidy up your animal photo-ID catalog: spot the same animal recorded
twice, find sightings filed under the wrong animal, and judge how reliable the automatic matching
is. Everything here is **read-only** — the tools only ever suggest; you make the changes in Wildbook.
These tools help you work with your animal photo-ID catalog in two ways: **check and tidy** the
catalog you already have, and **get new sightings into** it. Each tool's page tells your assistant
exactly what to do; you review and make the final decisions in Wildbook.

## What you'll need

A short-lived access token from Wildbook. In Wildbook, open your account menu and choose
**API Access** to create one, then paste **only that token** to your assistant — never your username
or password. The token has an expiration date that may vary by Wildbook; create a fresh one when it stops working.
Full technical detail is in the **api-reference** page (fetch `/api/v3/agent-skill/api-reference`).
Most tools here need a short-lived access token from Wildbook. In Wildbook, open your account menu
and choose **API Access** to create one, then paste **only that token** to your assistant — never
your username or password. The token has an expiration date that may vary by Wildbook; create a
fresh one when it stops working. Full technical detail is in the **api-reference** page (fetch
`/api/v3/agent-skill/api-reference`). The import-prep tools below are the exception — they need no
token, because they only prepare files you upload yourself.

## The toolbox
## Check and tidy your catalog (read-only — the tools only suggest; you make the changes in Wildbook)

| Tool | Use this when you want to… | Fetch |
|---|---|---|
Expand All @@ -20,13 +22,22 @@ Full technical detail is in the **api-reference** page (fetch `/api/v3/agent-ski
| how-good-is-our-matching | understand how reliable the automatic matching is for a species or site | `/api/v3/agent-skill/how-good-is-our-matching` |
| review-id-problems | go through suspected ID problems photo-by-photo and build a to-do list | `/api/v3/agent-skill/review-id-problems` |

## Get sightings into Wildbook (import prep — no token needed)

| Tool | Use this when you want to… | Fetch |
|---|---|---|
| inat-to-wildbook-import | pull recent iNaturalist sightings of your species and prepare them for bulk import | `/api/v3/agent-skill/inat-to-wildbook-import` |

## How this works

When you describe one of the tasks above to your AI assistant, it fetches that tool's page and follows the steps there. Each page tells the assistant exactly which catalog information to look up and how to show you what it finds — so you can review and decide.
When you describe one of the tasks above to your AI assistant, it fetches that tool's page and
follows the steps there. Each page tells the assistant exactly what to look up or run and how to
show you what it finds — so you can review and decide.

## Additional references

These tools are only a subset of the types of data management and scientific analysis tasks you can use this API and Wildbook. For more information about Wildbook, see these resources if needed:
These tools are only a subset of the data management and scientific analysis tasks you can do with
this API and Wildbook. For more information about Wildbook, see:
- [Wildbook Documentation](https://wildbook.docs.wildme.org/)
- [Wildbook Community](https://community.wildme.org/)
- [How I AI by Wildbook User Dr. Simon Pierce](https://github.com/simonjpierce/how-i-ai)
24 changes: 24 additions & 0 deletions src/test/java/org/ecocean/api/AgentSkillContentTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,33 @@ static void assertSkillStructure(String stem) {
assertTrue(index.contains(n), "index toolbox must list " + n);
assertTrue(index.contains("api-reference"), "index must reference api-reference");
// (c) the map's analytical keys are exactly those four (api-reference is the only extra)
assertTrue(AgentSkill.SKILL_RESOURCES.containsKey("inat-to-wildbook-import"),
"the import-prep skill must be registered");
java.util.Set<String> keys = new java.util.HashSet<>(AgentSkill.SKILL_RESOURCES.keySet());
keys.remove("api-reference");
keys.remove("inat-to-wildbook-import");
assertEquals(new java.util.HashSet<>(java.util.Arrays.asList(analytical)), keys,
"the analytical skills in the map must be exactly the four listed in the index");
}

@Test void inat_to_wildbook_import_is_well_formed() {
String md = load("/agent-skills/inat-to-wildbook-import.md");
assertFalse(md.isEmpty(), "inat-to-wildbook-import must be non-empty");
assertTrue(md.contains("name: inat-to-wildbook-import"),
"frontmatter name must equal the file stem");
for (String s : REQUIRED_SECTIONS)
assertTrue(md.contains(s), "import skill must contain section " + s);
assertTrue(md.contains("github.com/WildMeOrg/inat-download-recent-species-sightings"),
"must point at the public repo");
assertTrue(md.contains("v1.0.0"), "must pin to the released tag");
assertTrue(md.contains("Encounter.otherCatalogNumbers"),
"must name the dedup back-reference column");
assertTrue(md.toLowerCase().contains("bulk import"),
"must hand off to the Wildbook Bulk Import UI");
assertNoLeak(md);
assertNoJargon(userFacingSections(md));
// it is an import-prep skill, so it must NOT be forced through the read-only template
assertTrue(load("/agent-skills/index.md").contains("inat-to-wildbook-import"),
"root index must list the import skill");
}
}
Loading