Problem
OpenOSINT is currently optimized for interactive and tool-driven use via the CLI, REPL, and MCP surfaces. That is valuable for day-to-day investigations, but it makes the project difficult to consume as a library inside orchestration systems, automation pipelines, and higher-level OSINT applications.
Today, there is no stable public Python entry point that a caller can rely on for programmatic use. Downstream projects must reach into implementation details, follow migration-specific internal modules, or shell out to commands instead of importing a supported API.
This creates several practical problems:
- orchestration / workflow engines cannot use OpenOSINT as a dependency with a stable contract
- there is no clear interface for typed investigations (email, domain, username, IP, URL, person, etc.)
- budget and timeout controls are not exposed in a public, documented way
- it is difficult to integrate OpenOSINT with other systems without depending on CLI behavior
- the project is effectively CLI-first rather than library-first for programmatic use cases
This is particularly relevant when OpenOSINT is used as one component in a larger investigation stack, where a coordinator or orchestrator may need to call the project directly from Python, pass a target and investigation budget, and inspect the resulting entity graph without going through the REPL or MCP layer.
Proposal
Introduce a small, documented public Python API that intentionally exposes a stable, high-level investigation contract while leaving the lower-level implementation details in place.
The goal is not to replace the current human-facing interfaces. Rather, the goal is to add a supported programmatic surface that is explicit, typed, and documented for downstream callers.
The proposal is to add a public investigate() entry point and a small set of supporting types that map to the existing investigation engine without exposing implementation internals.
In practice, this means:
openosint.investigate.investigate() becomes the supported high-level entry point- callers can pass a target string plus optional investigation kind and budget
- callers can attach an optional
run_id for correlation/logging - callers receive the same
EntityGraph used internally, without having to know about private helpers or tool orchestration implementation details - the public API remains lightweight and avoids forcing every caller to understand the full pivot/graph subsystem
This keeps the current interactive surfaces intact while enabling a clean dependency path for orchestrators and agentic systems.
API contract
The intended public contract looks like:
importasynciofromopenosintimportinvestigatefromopenosint.graph.export.stiximportto_stix_jsongraph=asyncio.run(investigate("example.com"))
print(to_stix_json(graph))The API can also support typed investigations:
importasynciofromopenosint.investigateimportinvestigate, InvestigationBudget, EntityKindbudget=InvestigationBudget(max_depth=3, max_entities=60, max_tool_calls=80)
graph=asyncio.run(
investigate(
"johndoe99",
kind=EntityKind.USERNAME,
budget=budget,
run_id="daily-2026-09-04",
)
)
Proposed public symbols:
openosint.investigate.investigate()openosint.investigate.EntityKindopenosint.investigate.InvestigationBudget- package-root re-exports from
openosint.__init__ for convenience
This keeps the interface narrow and stable while aligning with the project’s current graph model and investigation semantics.
Compatibility plan
This proposal is deliberately additive and compatibility-safe:
- Existing CLI, REPL, and MCP workflows remain unchanged.
- The public API sits on top of the current investigation engine instead of replacing it.
- The existing
pivot.investigate_graph() remains the underlying implementation detail. - The wrapper validates input and normalizes budget values before invocation.
- The public contract is intentionally small and documentation-friendly.
- STIX export and graph export remain optional, behind the existing extra dependencies, so current installations remain unaffected unless callers opt in.
This is a low-risk path because it does not require changing the current operational model or removing existing user interfaces. It simply provides the missing contract that external orchestration code needs to consume OpenOSINT in a supported, predictable way.
Why this matters
Adding a stable public API is not a cosmetic change. It is the difference between OpenOSINT being a local interactive tool and OpenOSINT being a reusable investigation primitive inside broader systems.
If we want OpenOSINT to be used as a dependency by orchestrators, automation frameworks, and downstream intelligence systems, then the library surface must be explicit and supported. This proposal gives maintainers a clear and minimal way to do that without destabilizing the current CLI-first experience.
Problem
OpenOSINT is currently optimized for interactive and tool-driven use via the CLI, REPL, and MCP surfaces. That is valuable for day-to-day investigations, but it makes the project difficult to consume as a library inside orchestration systems, automation pipelines, and higher-level OSINT applications.
Today, there is no stable public Python entry point that a caller can rely on for programmatic use. Downstream projects must reach into implementation details, follow migration-specific internal modules, or shell out to commands instead of importing a supported API.
This creates several practical problems:
This is particularly relevant when OpenOSINT is used as one component in a larger investigation stack, where a coordinator or orchestrator may need to call the project directly from Python, pass a target and investigation budget, and inspect the resulting entity graph without going through the REPL or MCP layer.
Proposal
Introduce a small, documented public Python API that intentionally exposes a stable, high-level investigation contract while leaving the lower-level implementation details in place.
The goal is not to replace the current human-facing interfaces. Rather, the goal is to add a supported programmatic surface that is explicit, typed, and documented for downstream callers.
The proposal is to add a public
investigate()entry point and a small set of supporting types that map to the existing investigation engine without exposing implementation internals.In practice, this means:
openosint.investigate.investigate()becomes the supported high-level entry pointrun_idfor correlation/loggingEntityGraphused internally, without having to know about private helpers or tool orchestration implementation detailsThis keeps the current interactive surfaces intact while enabling a clean dependency path for orchestrators and agentic systems.
API contract
The intended public contract looks like:
The API can also support typed investigations:
Proposed public symbols:
openosint.investigate.investigate()openosint.investigate.EntityKindopenosint.investigate.InvestigationBudgetopenosint.__init__for convenienceThis keeps the interface narrow and stable while aligning with the project’s current graph model and investigation semantics.
Compatibility plan
This proposal is deliberately additive and compatibility-safe:
pivot.investigate_graph()remains the underlying implementation detail.This is a low-risk path because it does not require changing the current operational model or removing existing user interfaces. It simply provides the missing contract that external orchestration code needs to consume OpenOSINT in a supported, predictable way.
Why this matters
Adding a stable public API is not a cosmetic change. It is the difference between OpenOSINT being a local interactive tool and OpenOSINT being a reusable investigation primitive inside broader systems.
If we want OpenOSINT to be used as a dependency by orchestrators, automation frameworks, and downstream intelligence systems, then the library surface must be explicit and supported. This proposal gives maintainers a clear and minimal way to do that without destabilizing the current CLI-first experience.