From 474fc173c96b1ded07db7a1fbd37aa12e9abc1d9 Mon Sep 17 00:00:00 2001 From: Andres Contreras Date: Thu, 8 Oct 2026 19:06:53 -0700 Subject: [PATCH 1/2] Unify Agentic documentation with the Framework family identity --- README.md | 2 +- assets/README.md | 55 ++-- assets/agent-anatomy.svg | 122 ++++---- assets/architecture.svg | 102 +++---- assets/banner-light.svg | 1 + assets/banner.svg | 39 +-- assets/brand-logo-light.svg | 1 + assets/brand-logo.svg | 10 +- assets/ecosystem.svg | 102 +++---- assets/favicon.svg | 1 + assets/logo.svg | 1 + assets/model-routing.svg | 106 +++---- assets/pipeline.svg | 132 ++++----- assets/protocols.svg | 112 +++---- assets/rag.svg | 110 +++---- assets/reasoning.svg | 114 ++++---- assets/tools/brand-source/NOTICE.md | 13 + assets/tools/brand-source/ORIGIN.json | 37 +++ assets/tools/brand-source/banner-dark.svg | 1 + assets/tools/brand-source/banner-light.svg | 1 + assets/tools/brand-source/firefly-light.svg | 1 + assets/tools/brand-source/logo-dark-mono.svg | 1 + assets/tools/brand-source/logo-dark.svg | 1 + assets/tools/brand-source/logo-light-mono.svg | 1 + assets/tools/brand-source/logo-light.svg | 1 + assets/tools/build_brand_assets.py | 276 ++++++++---------- assets/workflows.svg | 108 +++---- docs/assets/agent-anatomy.svg | 122 ++++---- docs/assets/architecture.svg | 102 +++---- docs/assets/banner-light.svg | 1 + docs/assets/banner.svg | 39 +-- docs/assets/brand-logo-light.svg | 1 + docs/assets/brand-logo.svg | 10 +- docs/assets/ecosystem.svg | 102 +++---- docs/assets/favicon.svg | 23 +- docs/assets/fonts/Manrope-variable.woff2 | Bin 0 -> 24836 bytes docs/assets/fonts/OFL.txt | 93 ++++++ docs/assets/logo.svg | 26 +- docs/assets/model-routing.svg | 106 +++---- docs/assets/pipeline.svg | 132 ++++----- docs/assets/protocols.svg | 112 +++---- docs/assets/rag.svg | 110 +++---- docs/assets/reasoning.svg | 114 ++++---- docs/assets/workflows.svg | 108 +++---- docs/javascripts/constellation.js | 12 +- docs/stylesheets/firefly.css | 181 ++++++------ mkdocs.yml | 10 +- overrides/home.html | 6 +- 48 files changed, 1436 insertions(+), 1425 deletions(-) create mode 100644 assets/banner-light.svg create mode 100644 assets/brand-logo-light.svg create mode 100644 assets/favicon.svg create mode 100644 assets/logo.svg create mode 100644 assets/tools/brand-source/NOTICE.md create mode 100644 assets/tools/brand-source/ORIGIN.json create mode 100644 assets/tools/brand-source/banner-dark.svg create mode 100644 assets/tools/brand-source/banner-light.svg create mode 100644 assets/tools/brand-source/firefly-light.svg create mode 100644 assets/tools/brand-source/logo-dark-mono.svg create mode 100644 assets/tools/brand-source/logo-dark.svg create mode 100644 assets/tools/brand-source/logo-light-mono.svg create mode 100644 assets/tools/brand-source/logo-light.svg create mode 100644 docs/assets/banner-light.svg create mode 100644 docs/assets/brand-logo-light.svg create mode 100644 docs/assets/fonts/Manrope-variable.woff2 create mode 100644 docs/assets/fonts/OFL.txt diff --git a/README.md b/README.md index 5f5f67f5..7ab41507 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Firefly Agentic — production-grade agents, reasoning and pipelines, built on Pydantic AI + agentic by Firefly — Intelligence, composed.

Firefly Agentic

diff --git a/assets/README.md b/assets/README.md index 75b4c44d..e6fd2cff 100644 --- a/assets/README.md +++ b/assets/README.md @@ -1,8 +1,10 @@ # Firefly Agentic brand assets -Firefly Agentic shares the [Firefly Framework](https://github.com/fireflyframework) -wordmark and amber firefly glow-dot, with a violet palette for the agentic project. -These SVGs appear in the README and documentation site. +Firefly Agentic uses the lowercase `agentic` wordmark in Manrope 500, with the +original Firefly trail on its terminal `c` and the unchanged `by firefly` +endorsement. Charcoal, ivory, and amber connect the documentation to the +[Framework family](https://github.com/fireflyframework). The product and API +name remains Firefly Agentic. ## Diagrams @@ -13,8 +15,9 @@ supports the same features. | Asset | Dimensions | Purpose | |-------|------------|---------| -| [`brand-logo.svg`](brand-logo.svg) | 300 × 64 | Compact Firefly Agentic wordmark for the documentation header and mobile navigation. | -| [`banner.svg`](banner.svg) | 1280 × 320 | Firefly wordmark, Agentic lockup and a constellation of connected agents. | +| [`brand-logo.svg`](brand-logo.svg), [`brand-logo-light.svg`](brand-logo-light.svg) | Original master viewBox | Outlined Agentic lockup for dark and light surfaces. The dark-surface variant is also generated as `logo.svg`. | +| [`banner.svg`](banner.svg), [`banner-light.svg`](banner-light.svg) | 1600 × 480 | Canonical Agentic lockup and “Intelligence, composed.” in both themes. | +| [`favicon.svg`](favicon.svg) | 128 × 128 | The exact terminal `c` path and original trail gradient on charcoal. | | [`architecture.svg`](architecture.svg) | 1100 × 710 | FireflyAgent, tools, memory and model configuration, with optional composition around the Pydantic AI 2 engine. | | [`agent-anatomy.svg`](agent-anatomy.svg) | 1100 × 760 | A normal successful agent run, with default and optional middleware shown separately. | | [`model-routing.svg`](model-routing.svg) | 1100 × 690 | Effective model selection and ModelOptions validation; explicit Chat, Responses and other provider routes. | @@ -25,24 +28,30 @@ supports the same features. | [`rag.svg`](rag.svg) | 1100 × 660 | Eight embedding providers, six vector backends and the indexing/query flow; compatibility remains a configuration concern. | | [`ecosystem.svg`](ecosystem.svg) | 1100 × 672 | Related Firefly projects, without implying API or feature parity across runtimes. | -`docs/assets/` contains byte-identical generated copies for the documentation -site. Its `logo.svg` and `favicon.svg` are separate site identity assets and are -not produced by this generator. +`docs/assets/` contains byte-identical generated copies of all 15 assets, +including the header logo and favicon. ## Design system -- **Wordmark:** the shared Firefly logo is embedded as vector paths, including - the amber glow-dot. No image or font download is required. -- **Palette:** violet `#8b5cf6`, `#7c3aed` and `#6d28d9`; deep violet `#4c1d95`; - ink `#1e1633`; body text `#322b45`; light panel `#f5f2fe`; stroke `#e4def5`. - The shared glow-dot uses `#FFF9C1` to `#F68000`. +- **Wordmark:** canonical outlined masters are recorded in + [`tools/brand-source/ORIGIN.json`](tools/brand-source/ORIGIN.json), including + their SHA-256 hashes and the canonical website generator hash. Generation + verifies these hashes before using the artwork. Nested endorsement dimensions + are retained when placing a master. +- **Palette:** charcoal `#10110f`, ivory `#f3f1eb`, amber `#ffb34a`, graphite + `#272820`, muted text `#62645b`, and border `#d8d4ca`. Amber title bands use + charcoal text; graphite title bands use ivory text. The generator checks + text contrast of at least 4.5:1; the current minimum is 5.32:1. - **Typography:** system sans text, with 16 px card headings and generally 14 px body text. Each view uses separate cards and generous spacing instead of dense inventories. Display diagrams at their natural aspect ratio and provide a link to the full-size SVG when embedding them at reduced widths. -- **Accessibility:** every SVG has a title, a descriptive text alternative and - `role="img"`. Titles and descriptions explain the relationships, not only the - file name. Embedding pages should still provide useful image alt text. + The documentation uses bundled Manrope with its + [SIL Open Font License](../docs/assets/fonts/OFL.txt); logos remain outlined. +- **Accessibility:** every technical diagram has a title, a descriptive text + alternative and `role="img"`. Titles and descriptions explain the + relationships, not only the file name. Brand masters retain their canonical + titles; embedding pages provide useful image alt text. - **Self-contained output:** no scripts, external images, external fonts or remote resource references. Wordmark and brand icons are vendored vector paths. @@ -55,18 +64,20 @@ python assets/tools/build_brand_assets.py python assets/tools/build_brand_assets.py --check ``` -The build writes the compact logo, banner and nine diagrams to both `assets/` and -`docs/assets/`. `--check` regenerates them in memory and exits unsuccessfully if +The build writes the logo variants, banner variants, favicon, and nine diagrams +to both `assets/` and `docs/assets/`. `--check` regenerates them in memory and exits unsuccessfully if any file is missing or differs; it does not change files. Both modes check card geometry and measured text fit. Fixed embedded character advances make layout identical across operating systems; the generator does not inspect local fonts. Rendering can use a different system fallback font, so visual inspection remains necessary after changes. -The generator imports the wordmark from [`tools/wordmark.py`](tools/wordmark.py) -and brand icons from [`tools/icons.py`](tools/icons.py). Those local sources and -[`tools/build_brand_assets.py`](tools/build_brand_assets.py) are authoritative; -edit them and regenerate instead of editing the resulting SVGs independently. +The generator reads the verified masters from `tools/brand-source/` and brand +icons from [`tools/icons.py`](tools/icons.py). To refresh the identity, export +the canonical masters, update their provenance, and regenerate. Edit diagram +layout in [`tools/build_brand_assets.py`](tools/build_brand_assets.py), rather +than editing output SVGs independently. Brand ownership terms are recorded in +[`tools/brand-source/NOTICE.md`](tools/brand-source/NOTICE.md). ## Previewing and checking diff --git a/assets/agent-anatomy.svg b/assets/agent-anatomy.svg index 231391e4..e648c6e0 100644 --- a/assets/agent-anatomy.svg +++ b/assets/agent-anatomy.svg @@ -1,72 +1,72 @@ A normal successful FireflyAgent run executes before middleware, loads attached conversation memory, resolves and validates model options, calls Pydantic AI 2, persists completed history, tracks configured usage, and executes after hooks in reverse orderA normal successful FireflyAgent run executes before middleware, loads attached conversation memory, resolves and validates model options, calls Pydantic AI 2, persists completed history, tracks configured usage, and executes after hooks in reverse order. Default middleware is logging plus observability when enabled; guards, caching, validation, retry, and circuit breaker middleware are optional. Error hooks run on failures. Cache middleware can return early. - - - - - - - - - - - - - - - - Anatomy of an agent run - fireflyframework-agentic - - A normal successful run through FireflyAgent; middleware can also short-circuit a request. - + + + + + + + + + + + + + + + agentic by Firefly + Anatomy of an agent run + fireflyframework-agentic + + A normal successful run through FireflyAgent; middleware can also short-circuit a request. + -1. Before-run middleware -Run configured hooks in order; a cache hit may return early. - - +1. Before-run middleware +Run configured hooks in order; a cache hit may return early. + + -2. Load attached memory -MemoryManager + conversation_id inject conversation history. - - +2. Load attached memory +MemoryManager + conversation_id inject conversation history. + + -3. Resolve model and ModelOptions -Validate and translate options for the effective model and API. - - -4. Execute with Pydantic AI 2 -Model/tool exchange, structured output or streaming. - - +3. Resolve model and ModelOptions +Validate and translate options for the effective model and API. + + +4. Execute with Pydantic AI 2 +Model/tool exchange, structured output or streaming. + + -5. Complete the run -Persist completed history and record enabled usage tracking. -Run after-hooks in reverse order; error-hooks handle failures. - +5. Complete the run +Persist completed history and record enabled usage tracking. +Run after-hooks in reverse order; error-hooks handle failures. + -Default middleware -LoggingMiddleware -ObservabilityMiddleware -only when observability is on -default_middleware=False opts out - +Default middleware +LoggingMiddleware +ObservabilityMiddleware +only when observability is on +default_middleware=False opts out + -Optional middleware -Prompt and output guards -Cost, cache and prompt cache -Explainability and validation -Retry and circuit breaker -Supply a middleware list - +Optional middleware +Prompt and output guards +Cost, cache and prompt cache +Explainability and validation +Retry and circuit breaker +Supply a middleware list + -Optional agent behavior -BaseTool / ToolKit / @tool -MemoryManager -Delegation and model fallback -Approval / deferred tool results -Enable and configure as needed -Middleware hooks wrap the run; tool guards wrap tool execution. These are separate extension points. -Provider and API capabilities still govern tools, reasoning, sampling and streaming. +Optional agent behavior +BaseTool / ToolKit / @tool +MemoryManager +Delegation and model fallback +Approval / deferred tool results +Enable and configure as needed +Middleware hooks wrap the run; tool guards wrap tool execution. These are separate extension points. +Provider and API capabilities still govern tools, reasoning, sampling and streaming. diff --git a/assets/architecture.svg b/assets/architecture.svg index 026fefcf..f6810740 100644 --- a/assets/architecture.svg +++ b/assets/architecture.svg @@ -1,60 +1,60 @@ Firefly Agentic architectureFirefly Agentic architecture. Applications use FireflyAgent or the firefly_agent decorator with Firefly tools, memory, and typed ModelOptions. Optional reasoning, orchestration, retrieval, and operational modules compose around that API. Pydantic AI 2 supplies the model engine. This view groups capabilities rather than claiming a strict dependency hierarchy. - - - - - - - - - - - - - - - - Architecture at a glance - fireflyframework-agentic - - The application API and the capabilities you compose around it; this is not an import-dependency graph. - + + + + + + + + + + + + + + + agentic by Firefly + Architecture at a glance + fireflyframework-agentic + + The application API and the capabilities you compose around it; this is not an import-dependency graph. + -Your application: FireflyAgent or @firefly_agent -Typed inputs and outputs · run / run_sync / run_stream · configure a model once, override per run - - - - +Your application: FireflyAgent or @firefly_agent +Typed inputs and outputs · run / run_sync / run_stream · configure a model once, override per run + + + + -Firefly tools -@tool · BaseTool · ToolKit -Guards and tool-call hooks -Adapted to the agent engine - +Firefly tools +@tool · BaseTool · ToolKit +Guards and tool-call hooks +Adapted to the agent engine + -Firefly memory -MemoryManager -Conversation + working memory -In-memory · file · SQLite -PostgreSQL · MongoDB - +Firefly memory +MemoryManager +Conversation + working memory +In-memory · file · SQLite +PostgreSQL · MongoDB + -Firefly model configuration -ModelOptions: typed run controls -ModelSpec / ModelFactory -Provider setup and credentials -Explicit Chat / Responses routes - +Firefly model configuration +ModelOptions: typed run controls +ModelSpec / ModelFactory +Provider setup and credentials +Explicit Chat / Responses routes + -Compose what the application needs -Reasoning patterns · pipelines and workflows · retrieval with embeddings and vector stores -Middleware · validation · observability · explainability · experiments and lab - - -Pydantic AI 2 engine -Provider clients · model/tool exchange · structured output · streaming (subject to model and API support) -Configuration, storage, resilience and security support these capabilities across the framework. +Compose what the application needs +Reasoning patterns · pipelines and workflows · retrieval with embeddings and vector stores +Middleware · validation · observability · explainability · experiments and lab + + +Pydantic AI 2 engine +Provider clients · model/tool exchange · structured output · streaming (subject to model and API support) +Configuration, storage, resilience and security support these capabilities across the framework. diff --git a/assets/banner-light.svg b/assets/banner-light.svg new file mode 100644 index 00000000..db465f77 --- /dev/null +++ b/assets/banner-light.svg @@ -0,0 +1 @@ +agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file diff --git a/assets/banner.svg b/assets/banner.svg index d30af40b..a2558904 100644 --- a/assets/banner.svg +++ b/assets/banner.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - agentic - - - Production-grade agents, reasoning & pipelines - type-safe · model-agnostic · built on Pydantic AI · async-native - fireflyframework-agentic - +agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file diff --git a/assets/brand-logo-light.svg b/assets/brand-logo-light.svg new file mode 100644 index 00000000..e22f3bb6 --- /dev/null +++ b/assets/brand-logo-light.svg @@ -0,0 +1 @@ +agentic by Firefly \ No newline at end of file diff --git a/assets/brand-logo.svg b/assets/brand-logo.svg index 4f77bd54..76b129ec 100644 --- a/assets/brand-logo.svg +++ b/assets/brand-logo.svg @@ -1,9 +1 @@ - - Firefly Agentic - Firefly wordmark with the amber glow and Agentic name on a dark violet background. - - - - - agentic - +agentic by Firefly \ No newline at end of file diff --git a/assets/ecosystem.svg b/assets/ecosystem.svg index b13321d5..b9bcb8ed 100644 --- a/assets/ecosystem.svg +++ b/assets/ecosystem.svg @@ -1,62 +1,62 @@ The Firefly family includes Java and Spring Boot, .NET, Python PyFly, Rust, Go, Angular frontend, and Agentic for agents, reasoning, and retrievalThe Firefly family includes Java and Spring Boot, .NET, Python PyFly, Rust, Go, Angular frontend, and Agentic for agents, reasoning, and retrieval. Each project has its own APIs and lifecycle; the diagram does not imply universal feature parity. - - - - - - - - - - - - - - - - The Firefly family - fireflyframework-agentic - - Related projects for application services, frontends and agentic systems. - - - - - - - - - -FRAMEWORK - + + + + + + + + + + + + + + + agentic by Firefly + The Firefly family + fireflyframework-agentic + + Related projects for application services, frontends and agentic systems. + + + + + + + + +Firefly +FRAMEWORK + -Java / Spring Boot -Application services - +Java / Spring Boot +Application services + -.NET -Application services - +.NET +Application services + -PyFly -Python application services - +PyFly +Python application services + -Rust -Async application services - +Rust +Async application services + -Go -Developer tooling - +Go +Developer tooling + -Frontend -Angular · flyfront - - +Frontend +Angular · flyfront + + Agentic -Agents · reasoning · retrieval -A shared family identity; each project documents its own APIs, features and lifecycle. +Agents · reasoning · retrieval +A shared family identity; each project documents its own APIs, features and lifecycle. diff --git a/assets/favicon.svg b/assets/favicon.svg new file mode 100644 index 00000000..942de307 --- /dev/null +++ b/assets/favicon.svg @@ -0,0 +1 @@ +agentic diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 00000000..76b129ec --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1 @@ +agentic by Firefly \ No newline at end of file diff --git a/assets/model-routing.svg b/assets/model-routing.svg index 11da75bc..f539b756 100644 --- a/assets/model-routing.svg +++ b/assets/model-routing.svg @@ -1,62 +1,62 @@ Model routing through FireflyAgentModel routing through FireflyAgent. Resolve the effective model, merge typed ModelOptions, validate against the model profile, and translate to native settings. Firefly preserves legacy openai and azure aliases as Chat Completions; openai-responses and azure-responses explicitly select Responses. Other providers use their own adapters. Existing model objects retain their class and client. Support depends on the selected model and API, and unsupported explicit controls raise ModelOptionsError. - - - - - - - - - - - - - - - - One application API, explicit model routes - fireflyframework-agentic - - Keep agent behavior in Firefly; select the provider and API deliberately. - + + + + + + + + + + + + + + + agentic by Firefly + One application API, explicit model routes + fireflyframework-agentic + + Keep agent behavior in Firefly; select the provider and API deliberately. + -FireflyAgent / @firefly_agent -Firefly tools + MemoryManager + ModelOptions - - +FireflyAgent / @firefly_agent +Firefly tools + MemoryManager + ModelOptions + + -Resolve the effective model and validate typed options -Configured model or per-run override; preserve an existing model object's class and client. -Merge ModelOptions, validate against the model/profile, then translate to native request settings. - - - - - - +Resolve the effective model and validate typed options +Configured model or per-run override; preserve an existing model object's class and client. +Merge ModelOptions, validate against the model/profile, then translate to native request settings. + + + + + + -Chat Completions -openai: · openai-chat: -azure: · azure-chat: -Legacy aliases keep Chat -OpenAI / Azure Chat API - +Chat Completions +openai: · openai-chat: +azure: · azure-chat: +Legacy aliases keep Chat +OpenAI / Azure Chat API + -Responses -openai-responses: -azure-responses: -Explicit Responses selection -OpenAI / Azure Responses API - +Responses +openai-responses: +azure-responses: +Explicit Responses selection +OpenAI / Azure Responses API + -Other model providers -For example: Anthropic, Google -Provider-specific adapters -ModelSpec / ModelFactory -support configured clients -Per-run fields override agent options; explicit None clears an inherited field. -Unsupported explicit controls fail early with ModelOptionsError. Feature support varies by model and API. -Advanced escape hatch: native model_settings; they do not change the selected API route. +Other model providers +For example: Anthropic, Google +Provider-specific adapters +ModelSpec / ModelFactory +support configured clients +Per-run fields override agent options; explicit None clears an inherited field. +Unsupported explicit controls fail early with ModelOptionsError. Feature support varies by model and API. +Advanced escape hatch: native model_settings; they do not change the selected API route. diff --git a/assets/pipeline.svg b/assets/pipeline.svg index 7dbe7334..7d7fdf89 100644 --- a/assets/pipeline.svg +++ b/assets/pipeline.svg @@ -1,79 +1,79 @@ An example document-processing DAG ingests and splits, classifies, extracts in parallel, validates, assembles, and explainsAn example document-processing DAG ingests and splits, classifies, extracts in parallel, validates, assembles, and explains. It illustrates an application composition rather than mandatory stages. PipelineBuilder and PipelineEngine also support explicitly enabled cycles with visit limits. Pause requests external input; Send dispatches worker payloads. Checkpointing and audit/event sinks are configurable. - - - - - - - - - - - - - - - - Pipelines: declarative graphs and explicit state - fireflyframework-agentic - - Build a DAG for parallel stages, or enable cyclic routing for iterative work. -EXAMPLE: DOCUMENT PROCESSING DAG - + + + + + + + + + + + + + + + agentic by Firefly + Pipelines: declarative graphs and explicit state + fireflyframework-agentic + + Build a DAG for parallel stages, or enable cyclic routing for iterative work. +EXAMPLE: DOCUMENT PROCESSING DAG + -Ingest and split -BinaryNormalizer -DocumentSplitter - +Ingest and split +BinaryNormalizer +DocumentSplitter + -Classify -AgentStep -Typed document category - +Classify +AgentStep +Typed document category + -Extract in parallel -Send dispatches worker nodes -Reducers merge worker results - +Extract in parallel +Send dispatches worker nodes +Reducers merge worker results + -Validate -OutputReviewer -Application validation rules - +Validate +OutputReviewer +Application validation rules + -Assemble -Typed application output -Merge validated fields - +Assemble +Typed application output +Merge validated fields + -Explain -ReportBuilder -Build the processing report - - - - - - +Explain +ReportBuilder +Build the processing report + + + + + + -Control flow -Pause: wait for external input -Send: dispatch worker payloads -Cycles: opt in + visit limits - +Control flow +Pause: wait for external input +Send: dispatch worker payloads +Cycles: opt in + visit limits + -Checkpointing -Checkpointer / FileCheckpointer -Persist resumable run state -Resume from saved checkpoints - +Checkpointing +Checkpointer / FileCheckpointer +Persist resumable run state +Resume from saved checkpoints + -Audit and events -AuditLog records node results -Event handlers observe progress -Wire the sinks your app needs -PipelineBuilder + PipelineEngine · per-node conditions, retries and timeouts -The flow above is one application design; these stages are not a required pipeline sequence. +Audit and events +AuditLog records node results +Event handlers observe progress +Wire the sinks your app needs +PipelineBuilder + PipelineEngine · per-node conditions, retries and timeouts +The flow above is one application design; these stages are not a required pipeline sequence. diff --git a/assets/protocols.svg b/assets/protocols.svg index d639ee84..afb7be10 100644 --- a/assets/protocols.svg +++ b/assets/protocols.svg @@ -1,67 +1,67 @@ Selected Firefly extension contracts for agents, tools, models, reasoning, memory, content, retrieval, pipelines, and workflowsSelected Firefly extension contracts for agents, tools, models, reasoning, memory, content, retrieval, pipelines, and workflows. Protocol conformance describes a structural contract, not automatic registration. Abstract base classes provide subclass extension points. ModelOptions is typed configuration rather than a protocol. - - - - - - - - - - - - - - - - Extension contracts - fireflyframework-agentic - - Selected public protocols, grouped by responsibility; use the matching constructor, adapter or registry. - + + + + + + + + + + + + + + + agentic by Firefly + Extension contracts + fireflyframework-agentic + + Selected public protocols, grouped by responsibility; use the matching constructor, adapter or registry. + -Agents and tools -AgentLike · ToolProtocol -AgentMiddleware -GuardProtocol · ToolCallListener - +Agents and tools +AgentLike · ToolProtocol +AgentMiddleware +GuardProtocol · ToolCallListener + -Models and reasoning -CredentialResolver -ReasoningPattern -ValidationRule - +Models and reasoning +CredentialResolver +ReasoningPattern +ValidationRule + -Memory and content -MemoryStore · ContentSource -Chunker · CompressionStrategy -OfficeConverter - +Memory and content +MemoryStore · ContentSource +Chunker · CompressionStrategy +OfficeConverter + -Retrieval -EmbeddingProtocol -VectorStoreProtocol -ScopedVectorStore - +Retrieval +EmbeddingProtocol +VectorStoreProtocol +ScopedVectorStore + -Pipelines -StepExecutor · Checkpointer -AuditLog · QueryableAuditLog -EventHandler -PipelineEventHandler - +Pipelines +StepExecutor · Checkpointer +AuditLog · QueryableAuditLog +EventHandler +PipelineEventHandler + -Workflows -AgentRunner -StreamingAgentRunner -JournalBackend -ModelSelectionStrategy - +Workflows +AgentRunner +StreamingAgentRunner +JournalBackend +ModelSelectionStrategy + -Protocols and base classes have different roles -Protocols describe structural contracts. ABCs such as BaseTool, BaseEmbedder, BaseVectorStore -and StorageBackend provide explicit subclass extension points; matching a protocol does not register it. -ModelOptions is a typed configuration model, not an extension protocol. +Protocols and base classes have different roles +Protocols describe structural contracts. ABCs such as BaseTool, BaseEmbedder, BaseVectorStore +and StorageBackend provide explicit subclass extension points; matching a protocol does not register it. +ModelOptions is a typed configuration model, not an extension protocol. diff --git a/assets/rag.svg b/assets/rag.svg index 376d289c..0cc2c1c2 100644 --- a/assets/rag.svg +++ b/assets/rag.svg @@ -1,65 +1,65 @@ Firefly retrieval supports eight embedding providers and six vector-store backends behind EmbeddingProtocol and VectorStoreProtocolFirefly retrieval supports eight embedding providers and six vector-store backends behind EmbeddingProtocol and VectorStoreProtocol. Documents are upserted, text queries return SearchResult objects, and applications pass retrieved context to FireflyAgent. Automatic embedding and search_text require an attached embedder. Indexing and queries must use compatible embedding dimensions and the same embedding space; filtering and persistence vary by backend. - - - - - - - - - - - - - - - - Retrieval: a shared API for embeddings and vector stores - fireflyframework-agentic - - Select compatible embedding dimensions, provider configuration and backend behavior. - + + + + + + + + + + + + + + + agentic by Firefly + Retrieval: a shared API for embeddings and vector stores + fireflyframework-agentic + + Select compatible embedding dimensions, provider configuration and backend behavior. + -Embedding providers -OpenAI · Azure OpenAI -Cohere · Google -Mistral · Voyage AI -AWS Bedrock · Ollama - -EmbeddingProtocol -BaseEmbedder - +Embedding providers +OpenAI · Azure OpenAI +Cohere · Google +Mistral · Voyage AI +AWS Bedrock · Ollama + +EmbeddingProtocol +BaseEmbedder + -Vector store backends -InMemoryVectorStore -ChromaDB · Pinecone -Qdrant · pgvector -sqlite-vec - -VectorStoreProtocol -BaseVectorStore - +Vector store backends +InMemoryVectorStore +ChromaDB · Pinecone +Qdrant · pgvector +sqlite-vec + +VectorStoreProtocol +BaseVectorStore + -Index documents -VectorDocument -> upsert() - - +Index documents +VectorDocument -> upsert() + + -Search -search_text(query, top_k=5) - - +Search +search_text(query, top_k=5) + + -Use retrieved context -SearchResult -> FireflyAgent - - - +Use retrieved context +SearchResult -> FireflyAgent + + + -Compose retrieval with the rest of Firefly -An attached embedder enables automatic document embedding and search_text(). -TenantScopedVectorStore scopes namespaces; EmbeddingStep and RetrievalStep integrate with pipelines. -Indexing and querying must use the same embedding space. Backend filtering and persistence can differ. +Compose retrieval with the rest of Firefly +An attached embedder enables automatic document embedding and search_text(). +TenantScopedVectorStore scopes namespaces; EmbeddingStep and RetrievalStep integrate with pipelines. +Indexing and querying must use the same embedding space. Backend filtering and persistence can differ. diff --git a/assets/reasoning.svg b/assets/reasoning.svg index a6245294..6d204511 100644 --- a/assets/reasoning.svg +++ b/assets/reasoning.svg @@ -1,71 +1,71 @@ Six reasoning patterns share result and trace contractsSix reasoning patterns share result and trace contracts. ReAct, Chain of Thought, Plan-and-Execute, and Reflexion use the AbstractReasoningPattern template: reason, act, observe, and should_continue, with early stopping and iteration limits. Tree of Thoughts overrides execute to generate and score branches; Goal Decomposition overrides execute to coordinate phases and tasks. ReasoningPipeline composes patterns. - - - - - - - - - - - - - - - - Six reasoning patterns, shared contracts - fireflyframework-agentic - - Four patterns use the base template below; Tree of Thoughts and Goal Decomposition override execute(). - + + + + + + + + + + + + + + + agentic by Firefly + Six reasoning patterns, shared contracts + fireflyframework-agentic + + Four patterns use the base template below; Tree of Thoughts and Goal Decomposition override execute(). + -_reason - - +_reason + + -_act - - +_act + + -_observe - - +_observe + + -_should_continue - -Base template: ReAct · Chain of Thought · Plan-and-Execute · Reflexion - +_should_continue + +Base template: ReAct · Chain of Thought · Plan-and-Execute · Reflexion + -ReAct -Think, call a tool, observe -Interleaved reasoning and action - +ReAct +Think, call a tool, observe +Interleaved reasoning and action + -Chain of Thought -Structured intermediate steps -A final answer from those steps - +Chain of Thought +Structured intermediate steps +A final answer from those steps + -Plan-and-Execute -Create a plan, execute its steps -Replan when configured - +Plan-and-Execute +Create a plan, execute its steps +Replan when configured + -Reflexion -Execute, critique, retry -Use feedback on another attempt - +Reflexion +Execute, critique, retry +Use feedback on another attempt + -Tree of Thoughts -Generate and evaluate branches -Select the highest-scored branch - +Tree of Thoughts +Generate and evaluate branches +Select the highest-scored branch + -Goal Decomposition -Split a goal into sub-goals -Coordinate their execution -All return ReasoningResult with a trace; ReasoningPipeline composes patterns. +Goal Decomposition +Split a goal into sub-goals +Coordinate their execution +All return ReasoningResult with a trace; ReasoningPipeline composes patterns. diff --git a/assets/tools/brand-source/NOTICE.md b/assets/tools/brand-source/NOTICE.md new file mode 100644 index 00000000..4c8dcabf --- /dev/null +++ b/assets/tools/brand-source/NOTICE.md @@ -0,0 +1,13 @@ +# Brand ownership + +The Firefly and Framework names, wordmarks, marks, and graphic systems are +proprietary to Firefly Software Solutions Inc. All rights reserved. These +assets identify Firefly Agentic in its official documentation. The repository's +software license does not grant trademark rights or permission to imply an +endorsement. + +The canonical Agentic masters are exported from the Framework website identity +generator and preserved byte-for-byte with SHA-256 provenance in `ORIGIN.json`. +The Firefly endorsement is preserved unchanged. Manrope is licensed under the +SIL Open Font License 1.1; the redistributed font and license are in +`docs/assets/fonts/` at the repository root. diff --git a/assets/tools/brand-source/ORIGIN.json b/assets/tools/brand-source/ORIGIN.json new file mode 100644 index 00000000..6bf67953 --- /dev/null +++ b/assets/tools/brand-source/ORIGIN.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "canonicalRepository": "https://github.com/fireflyframework/fireflyframework.org", + "canonicalSource": "scripts/brand/agentic-identity.mjs", + "canonicalSourceSha256": "1f822f78516e8e56ec9ea6b97f87ef1d825575a4c72a7df07775cf4b36bd5118", + "brandKit": "https://github.com/fireflyframework/brand-kit", + "masters": [ + { + "path": "logo-dark.svg", + "sha256": "203a6c124abb229cc1609ba4423dc5560f7e02c54c1941133464fcf2053e8b3d" + }, + { + "path": "logo-light.svg", + "sha256": "8805cc50196df356692cb974120e74a9cd1f96e69f73053cf457881401c8e597" + }, + { + "path": "logo-dark-mono.svg", + "sha256": "94cd3e13ad0043eef734c459464942181219a7bd3ba9618f2bb953a90fd84708" + }, + { + "path": "logo-light-mono.svg", + "sha256": "d678859b104adfaada14d9b648037a866ca937ec1b7bf0c029f4b68ee097a945" + }, + { + "path": "banner-dark.svg", + "sha256": "d7938754500f58f12e7f3f81dc4cafaa2ee85423730638c315916f15f1ade6ae" + }, + { + "path": "banner-light.svg", + "sha256": "c9b7e970f00e84a0a488201d5ffee4678f36046eff500b11a5b25a2a4ec6589f" + }, + { + "path": "firefly-light.svg", + "sha256": "e365eff656bca5807f5bf722db0f3c7de5b72120ac158d043013df7f0c96fca2" + } + ] +} diff --git a/assets/tools/brand-source/banner-dark.svg b/assets/tools/brand-source/banner-dark.svg new file mode 100644 index 00000000..a2558904 --- /dev/null +++ b/assets/tools/brand-source/banner-dark.svg @@ -0,0 +1 @@ +agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file diff --git a/assets/tools/brand-source/banner-light.svg b/assets/tools/brand-source/banner-light.svg new file mode 100644 index 00000000..db465f77 --- /dev/null +++ b/assets/tools/brand-source/banner-light.svg @@ -0,0 +1 @@ +agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file diff --git a/assets/tools/brand-source/firefly-light.svg b/assets/tools/brand-source/firefly-light.svg new file mode 100644 index 00000000..c175598a --- /dev/null +++ b/assets/tools/brand-source/firefly-light.svg @@ -0,0 +1 @@ +Firefly \ No newline at end of file diff --git a/assets/tools/brand-source/logo-dark-mono.svg b/assets/tools/brand-source/logo-dark-mono.svg new file mode 100644 index 00000000..50adc362 --- /dev/null +++ b/assets/tools/brand-source/logo-dark-mono.svg @@ -0,0 +1 @@ +agentic by Firefly \ No newline at end of file diff --git a/assets/tools/brand-source/logo-dark.svg b/assets/tools/brand-source/logo-dark.svg new file mode 100644 index 00000000..76b129ec --- /dev/null +++ b/assets/tools/brand-source/logo-dark.svg @@ -0,0 +1 @@ +agentic by Firefly \ No newline at end of file diff --git a/assets/tools/brand-source/logo-light-mono.svg b/assets/tools/brand-source/logo-light-mono.svg new file mode 100644 index 00000000..59e9ac2b --- /dev/null +++ b/assets/tools/brand-source/logo-light-mono.svg @@ -0,0 +1 @@ +agentic by Firefly \ No newline at end of file diff --git a/assets/tools/brand-source/logo-light.svg b/assets/tools/brand-source/logo-light.svg new file mode 100644 index 00000000..e22f3bb6 --- /dev/null +++ b/assets/tools/brand-source/logo-light.svg @@ -0,0 +1 @@ +agentic by Firefly \ No newline at end of file diff --git a/assets/tools/build_brand_assets.py b/assets/tools/build_brand_assets.py index 55663412..86b886a4 100644 --- a/assets/tools/build_brand_assets.py +++ b/assets/tools/build_brand_assets.py @@ -5,7 +5,7 @@ Verify committed outputs: python assets/tools/build_brand_assets.py --check No generation dependencies or installed fonts are required. Embedded font -advances make layout deterministic across operating systems. The shared family +advances make layout deterministic across operating systems. The canonical Agentic wordmark and vendored icons remain vector paths, with no external resources. All outputs are written to assets/ and mirrored byte-for-byte to docs/assets/. Render with CairoSVG separately for visual inspection after content changes. @@ -13,7 +13,10 @@ from __future__ import annotations import argparse +import hashlib +import json import sys +import xml.etree.ElementTree as ET from html import escape from pathlib import Path @@ -21,25 +24,24 @@ REPO = HERE.parents[1] ASSETS = REPO / "assets" sys.path.insert(0, str(HERE)) -from wordmark import FIREFLY_PATH, DOT_CX, DOT_CY, DOT_R from icons import ICONS # --------------------------------------------------------------------------- palette -WHITE = "#ffffff" -VIOLET = "#8b5cf6" -VIOLET2 = "#7c3aed" -VIOLETD = "#6d28d9" -MID = "#5b21b6" -DARK = "#4c1d95" -INK = "#1e1633" -BODY = "#322b45" -MUTED = "#756881" -SUB = "#f5f2fe" -STROKE = "#e4def5" -INDIGO = "#6366f1" -AMBER = "#c2722a" -DOT_HOT = "#F68000" -DOT_WARM = "#FFF9C1" +WHITE = "#f3f1eb" +ACCENT = "#ffb34a" +EDGE = "#62645b" +EDGE_DARK = "#474a42" +MID = "#62645b" +DARK = "#272820" +INK = "#10110f" +BODY = "#272820" +MUTED = "#62645b" +SUB = "#e9e7df" +STROKE = "#d8d4ca" +SECONDARY = "#62645b" +AMBER = "#8a5719" +DOT_HOT = "#ffb34a" +DOT_WARM = "#ffce82" MONO = "ui-monospace,'SF Mono',Menlo,Consolas,monospace" SANS = "-apple-system,'Segoe UI',Helvetica,Arial,sans-serif" @@ -277,18 +279,18 @@ def write_svg(name, svg): # --------------------------------------------------------------------------- kit def defs(cx, cy, r=520): return f''' - - - - - - - - - + + + + + + + + + - - + + ''' @@ -301,26 +303,46 @@ def frame(w, h): ) -def logo_w(h): - return 469.0 * h / 138.0 +MASTER_DIR = HERE / "brand-source" +MASTER_ORIGIN = json.loads((MASTER_DIR / "ORIGIN.json").read_text()) +MASTER_HASHES = {item["path"]: item["sha256"] for item in MASTER_ORIGIN["masters"]} +ET.register_namespace("", "http://www.w3.org/2000/svg") -def firefly_logo(x, cy, h=24, fill=VIOLET2, anchor="left"): - """The real Firefly wordmark logo — the embedded 'firefly' word + the amber - glow-dot, recolored. Vertical centre at cy; x is the left edge (anchor='left') - or the horizontal centre (anchor='mid'). Used as the brand mark in diagrams.""" - s = h / 138.0 - w = 469.0 * s - left = x - w / 2 if anchor == "mid" else x - tx = left - 4.0 * s - ty = cy - 105.45 * s # bbox y mid = (36.5+174.4)/2 - dcx = tx + DOT_CX * s - dcy = ty + DOT_CY * s - return ( - f'' - f'' - f'' - ) +def master(name): + data = (MASTER_DIR / name).read_bytes() + if hashlib.sha256(data).hexdigest() != MASTER_HASHES[name]: + raise ValueError(f"Brand master differs from its recorded origin: {name}") + return data.decode("utf-8") + + +def placed_master(name, x, y, width): + root = ET.fromstring(master(name)) + prefix = f"brand-{name.removesuffix('.svg')}-{x}-{y}".replace(".", "_") + ids = {node.attrib["id"]: f"{prefix}-{node.attrib['id']}" for node in root.iter() if "id" in node.attrib} + for node in root.iter(): + for key, value in list(node.attrib.items()): + if key == "id": + node.set(key, ids[value]) + else: + for previous, replacement in ids.items(): + value = value.replace(f"url(#{previous})", f"url(#{replacement})") + if value == f"#{previous}": + value = f"#{replacement}" + node.set(key, value) + _, _, w, h = map(float, root.attrib["viewBox"].split()) + root.set("x", str(x)) + root.set("y", str(y)) + root.set("width", str(width)) + root.set("height", str(width * h / w)) + return ET.tostring(root, encoding="unicode") + + +def firefly_logo(x, cy, h=24, anchor="left"): + root = ET.fromstring(master("firefly-light.svg")) + _, _, w, height = map(float, root.attrib["viewBox"].split()) + width = w * h / height + return placed_master("firefly-light.svg", x - width / 2 if anchor == "mid" else x, cy - h / 2, width) def icon(name, cx, cy, size, color=None): @@ -338,10 +360,10 @@ def icon(name, cx, cy, size, color=None): def title(w, t, sub=None, repo="fireflyframework-agentic"): s = [ - firefly_logo(26, 31, 25), - f'{esc(t)}', - f'{repo}', - f'', + placed_master("logo-light.svg", 26, 4, 98), + f'{esc(t)}', + f'{repo}', + f'', ] if sub: s.append(f'{esc(sub)}') @@ -370,7 +392,7 @@ def svgdoc(w, h, label, body, amb=None): WARN = [] -def arrow(x1, y1, x2, y2, color=VIOLETD, dash=None, mk="arr", sw=1.8): +def arrow(x1, y1, x2, y2, color=EDGE_DARK, dash=None, mk="arr", sw=1.8): d = f' stroke-dasharray="{dash}"' if dash else "" return f'' @@ -392,81 +414,8 @@ def check(name, rects, pad=2): # --------------------------------------------------------------------------- banner def build_banner(): - W, H = 1280, 320 - wx, wy, ws = 80, 116, 0.74 - dot_x, dot_y = wx + ws * DOT_CX, wy + ws * DOT_CY - wm_right = wx + ws * 469 - # a deliberate agent graph: input -> three agents -> two merge hubs -> output (+ 2 satellites) - GN = [ - (726, 162, 2.0, "a"), - (892, 98, 1.5, "v"), - (892, 162, 1.7, "v"), - (892, 226, 1.5, "v"), - (1052, 126, 1.5, "a"), - (1052, 200, 1.5, "a"), - (1212, 162, 1.95, "v"), - (986, 62, 0.85, "a"), - (1150, 258, 0.85, "v"), - ] - GE = [(0, 1), (0, 2), (0, 3), (1, 4), (2, 4), (2, 5), (3, 5), (4, 6), (5, 6), (7, 1), (8, 5)] - gx = lambda i: GN[i][0] - gy = lambda i: GN[i][1] - hero = lambda a, b: a in (0, 6) or b in (0, 6) - node = "".join(f'' for x, y, s, k in GN) - edges = "".join( - f'' - for a, b in GE - ) - bg = [ - (700, 56, 1.1, 0.4), - (840, 298, 0.9, 0.3), - (1244, 84, 1.0, 0.32), - (1176, 300, 0.9, 0.3), - (958, 300, 0.8, 0.26), - (1108, 40, 1.0, 0.3), - (660, 150, 0.8, 0.3), - ] - motes = "".join(f'' for x, y, r, o in bg) - svg = f''' - - - - - - - - - - - - - - - - - - - {motes} - {edges} - - - - - {node} - - - - - - agentic - - - Production-grade agents, reasoning & pipelines - type-safe · model-agnostic · built on Pydantic AI · async-native - fireflyframework-agentic - -''' - write_svg("banner.svg", svg) + write_svg("banner.svg", master("banner-dark.svg")) + write_svg("banner-light.svg", master("banner-light.svg")) # --------------------------------------------------------------------------- diagram kit @@ -489,15 +438,15 @@ def panel(x, y, w, h, header, lines=(), *, rects, dark=False, accent=False, size fill = "url(#bed)" if dark else "url(#card)" band = "url(#door)" if accent else "url(#hdr)" out = [ - f'' + f'' ] if not dark: out.append(f'') - out.append(text_line(x + 18, y + 24, header, 16, bold=True, color="#fff")) + out.append(text_line(x + 18, y + 24, header, 16, bold=True, color=INK if accent and not dark else WHITE)) for i, line in enumerate(lines): if tw(line, size) > w - 36: WARN.append(f"text does not fit panel {header}: {line}") - out.append(text_line(x + 18, y + 57 + i * 23, line, size, color="#e1d8f3" if dark else BODY)) + out.append(text_line(x + 18, y + 57 + i * 23, line, size, color="#f3f1eb" if dark else BODY)) return "\n".join(out) @@ -708,7 +657,7 @@ def model_routing(): ) ) b.append(arrow(550, 328, 550, 353)) - b.append(f'') + b.append(f'') for x in (206, 550, 894): b.append(arrow(x, 373, x, 385)) routes = [ @@ -1201,7 +1150,7 @@ def rag(): b.append(arrow(550, 317, 550, 344)) b.append(panel(402, 346, 296, 88, "Use retrieved context", ["SearchResult -> FireflyAgent"], rects=r)) b.append(arrow(371, 164, 400, 164, dash="4 3")) - b.append(arrow(729, 272, 700, 272, INDIGO, dash="4 3", mk="arrb")) + b.append(arrow(729, 272, 700, 272, SECONDARY, dash="4 3", mk="arrb")) b.append( panel( 42, @@ -1256,10 +1205,10 @@ def ecosystem(): ] for name, meta, ic, x, y in members: b.append( - f'' + f'' ) - b.append(f'') - b.append(firefly_logo(cx, cy - 17, 32, fill=MID, anchor="mid")) + b.append(f'') + b.append(firefly_logo(cx, cy - 17, 32, anchor="mid")) b.append(text_line(cx, cy + 27, "FRAMEWORK", 15, bold=True, anchor="middle", color=MID)) for name, meta, ic, x, y in members: width, height = 288, 85 @@ -1267,14 +1216,14 @@ def ecosystem(): r.append((left, top, left + width, top + height)) selected = name == "Agentic" b.append( - f'' + f'' ) if selected: - b.append(spark(left + 29, y - 9, 11, "#ffd07a")) + b.append(spark(left + 29, y - 9, 11, "#ffb34a")) else: b.append(icon(ic, left + 29, y - 9, 24)) b.append(text_line(left + 52, y - 3, name, 17, bold=True, color="#fff" if selected else INK)) - b.append(text_line(left + 18, y + 24, meta, 14, color="#eee7ff" if selected else BODY)) + b.append(text_line(left + 18, y + 24, meta, 14, color="#f3f1eb" if selected else BODY)) b.append( text_line( 550, @@ -1296,17 +1245,46 @@ def ecosystem(): def brand_logo(): - svg = f''' - Firefly Agentic - Firefly wordmark with the amber glow and Agentic name on a dark violet background. - - - {firefly_logo(14, 32, 36, fill="#eee7ff")} - - agentic - -''' - write_svg("brand-logo.svg", svg) + write_svg("brand-logo.svg", master("logo-dark.svg")) + write_svg("brand-logo-light.svg", master("logo-light.svg")) + write_svg("logo.svg", master("logo-dark.svg")) + source = ET.fromstring(master("logo-dark.svg")) + ns = {"s": "http://www.w3.org/2000/svg"} + gradient = source.find("s:defs", ns) + terminal = source.find('.//*[@data-agentic-terminal="trail-c"]') + write_svg("favicon.svg", 'agentic' + + ET.tostring(gradient, encoding="unicode") + + '' + + '' + + ET.tostring(terminal, encoding="unicode") + '\n') + + +def contrast(foreground, background): + def luminance(color): + values = [int(color[index:index + 2], 16) / 255 for index in (1, 3, 5)] + linear = [value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 for value in values] + return sum(value * weight for value, weight in zip(linear, (0.2126, 0.7152, 0.0722))) + light, dark = sorted((luminance(foreground), luminance(background)), reverse=True) + return (light + 0.05) / (dark + 0.05) + + +def check_palette(): + pairs = [(BODY, WHITE), (MUTED, WHITE), (WHITE, "#474a42"), (INK, ACCENT), (WHITE, DARK)] + ratios = [contrast(foreground, background) for foreground, background in pairs] + if min(ratios) < 4.5: + raise ValueError(f"Diagram text contrast falls below 4.5:1: {ratios}") + print(f"Text contrast: {min(ratios):.2f}:1 minimum across the diagram palette.") + + +def check_svg(name, drawing): + root = ET.fromstring(drawing) + ids = [node.attrib["id"] for node in root.iter() if "id" in node.attrib] + if len(ids) != len(set(ids)): + raise ValueError(f"Duplicate SVG IDs in {name}") + for node in root.iter(): + for key, value in node.attrib.items(): + if key.endswith("href") and value.startswith(("http:", "https:")): + raise ValueError(f"External resource in {name}: {value}") def main(): @@ -1315,6 +1293,7 @@ def main(): "--check", action="store_true", help="Verify generated SVGs and their docs mirrors without writing files." ) args = parser.parse_args() + check_palette() build_banner() brand_logo() for fn in (architecture, protocols, model_routing, reasoning, pipeline, workflows, rag, agent_anatomy, ecosystem): @@ -1323,6 +1302,7 @@ def main(): raise SystemExit("Diagram validation failed:\n" + "\n".join(WARN)) drift = [] for name, svg in OUTPUTS.items(): + check_svg(name, svg) for directory in (ASSETS, REPO / "docs" / "assets"): path = directory / name if args.check: diff --git a/assets/workflows.svg b/assets/workflows.svg index b05be48d..2497a723 100644 --- a/assets/workflows.svg +++ b/assets/workflows.svg @@ -1,63 +1,63 @@ Code-defined workflows use the workflow decorator and native Python control flowCode-defined workflows use the workflow decorator and native Python control flow. subworkflow is a callable primitive, not a decorator. WorkflowContext carries a runner, journal, budget, arguments, and events. FireflyAgentRunner is the default. Journal replay can reuse completed call results but does not make new model responses or arbitrary side effects deterministic. Verification helpers can evaluate outputs. - - - - - - - - - - - - - - - - Workflows: Python control flow around your agents - fireflyframework-agentic - - Use @workflow for code-defined orchestration; call run_workflow() or await the decorated workflow. - + + + + + + + + + + + + + + + agentic by Firefly + Workflows: Python control flow around your agents + fireflyframework-agentic + + Use @workflow for code-defined orchestration; call run_workflow() or await the decorated workflow. + -Your async workflow function -Native conditionals and loops; subworkflow() invokes another workflow. - - +Your async workflow function +Native conditionals and loops; subworkflow() invokes another workflow. + + -Workflow primitives -agent() · parallel() · pipeline() · stream() -phase() · human() · map_agents() · log() - - -WorkflowContext -current_workflow() carries the runner, journal, budget, arguments and events. - - +Workflow primitives +agent() · parallel() · pipeline() · stream() +phase() · human() · map_agents() · log() + + +WorkflowContext +current_workflow() carries the runner, journal, budget, arguments and events. + + -Runner -FireflyAgentRunner is the default -DefaultAgentRunner is optional -SmartRoutingRunner can select -models through routing strategies - - +Runner +FireflyAgentRunner is the default +DefaultAgentRunner is optional +SmartRoutingRunner can select +models through routing strategies + + -Journal -Completed calls can be replayed -FileJournalBackend persists runs -Resume uses recorded call results -External side effects need care - - +Journal +Completed calls can be replayed +FileJournalBackend persists runs +Resume uses recorded call results +External side effects need care + + -WorkflowBudget -Concurrent and total agents -Token and cost ceilings -Wall-clock timeout -Configure ceilings for your run -Verification helpers: cascade · adversarial_verify · judge_panel · loop_until_dry -Journal replay does not make fresh model calls or arbitrary Python side effects deterministic. +WorkflowBudget +Concurrent and total agents +Token and cost ceilings +Wall-clock timeout +Configure ceilings for your run +Verification helpers: cascade · adversarial_verify · judge_panel · loop_until_dry +Journal replay does not make fresh model calls or arbitrary Python side effects deterministic. diff --git a/docs/assets/agent-anatomy.svg b/docs/assets/agent-anatomy.svg index 231391e4..e648c6e0 100644 --- a/docs/assets/agent-anatomy.svg +++ b/docs/assets/agent-anatomy.svg @@ -1,72 +1,72 @@ A normal successful FireflyAgent run executes before middleware, loads attached conversation memory, resolves and validates model options, calls Pydantic AI 2, persists completed history, tracks configured usage, and executes after hooks in reverse orderA normal successful FireflyAgent run executes before middleware, loads attached conversation memory, resolves and validates model options, calls Pydantic AI 2, persists completed history, tracks configured usage, and executes after hooks in reverse order. Default middleware is logging plus observability when enabled; guards, caching, validation, retry, and circuit breaker middleware are optional. Error hooks run on failures. Cache middleware can return early. - - - - - - - - - - - - - - - - Anatomy of an agent run - fireflyframework-agentic - - A normal successful run through FireflyAgent; middleware can also short-circuit a request. - + + + + + + + + + + + + + + + agentic by Firefly + Anatomy of an agent run + fireflyframework-agentic + + A normal successful run through FireflyAgent; middleware can also short-circuit a request. + -1. Before-run middleware -Run configured hooks in order; a cache hit may return early. - - +1. Before-run middleware +Run configured hooks in order; a cache hit may return early. + + -2. Load attached memory -MemoryManager + conversation_id inject conversation history. - - +2. Load attached memory +MemoryManager + conversation_id inject conversation history. + + -3. Resolve model and ModelOptions -Validate and translate options for the effective model and API. - - -4. Execute with Pydantic AI 2 -Model/tool exchange, structured output or streaming. - - +3. Resolve model and ModelOptions +Validate and translate options for the effective model and API. + + +4. Execute with Pydantic AI 2 +Model/tool exchange, structured output or streaming. + + -5. Complete the run -Persist completed history and record enabled usage tracking. -Run after-hooks in reverse order; error-hooks handle failures. - +5. Complete the run +Persist completed history and record enabled usage tracking. +Run after-hooks in reverse order; error-hooks handle failures. + -Default middleware -LoggingMiddleware -ObservabilityMiddleware -only when observability is on -default_middleware=False opts out - +Default middleware +LoggingMiddleware +ObservabilityMiddleware +only when observability is on +default_middleware=False opts out + -Optional middleware -Prompt and output guards -Cost, cache and prompt cache -Explainability and validation -Retry and circuit breaker -Supply a middleware list - +Optional middleware +Prompt and output guards +Cost, cache and prompt cache +Explainability and validation +Retry and circuit breaker +Supply a middleware list + -Optional agent behavior -BaseTool / ToolKit / @tool -MemoryManager -Delegation and model fallback -Approval / deferred tool results -Enable and configure as needed -Middleware hooks wrap the run; tool guards wrap tool execution. These are separate extension points. -Provider and API capabilities still govern tools, reasoning, sampling and streaming. +Optional agent behavior +BaseTool / ToolKit / @tool +MemoryManager +Delegation and model fallback +Approval / deferred tool results +Enable and configure as needed +Middleware hooks wrap the run; tool guards wrap tool execution. These are separate extension points. +Provider and API capabilities still govern tools, reasoning, sampling and streaming. diff --git a/docs/assets/architecture.svg b/docs/assets/architecture.svg index 026fefcf..f6810740 100644 --- a/docs/assets/architecture.svg +++ b/docs/assets/architecture.svg @@ -1,60 +1,60 @@ Firefly Agentic architectureFirefly Agentic architecture. Applications use FireflyAgent or the firefly_agent decorator with Firefly tools, memory, and typed ModelOptions. Optional reasoning, orchestration, retrieval, and operational modules compose around that API. Pydantic AI 2 supplies the model engine. This view groups capabilities rather than claiming a strict dependency hierarchy. - - - - - - - - - - - - - - - - Architecture at a glance - fireflyframework-agentic - - The application API and the capabilities you compose around it; this is not an import-dependency graph. - + + + + + + + + + + + + + + + agentic by Firefly + Architecture at a glance + fireflyframework-agentic + + The application API and the capabilities you compose around it; this is not an import-dependency graph. + -Your application: FireflyAgent or @firefly_agent -Typed inputs and outputs · run / run_sync / run_stream · configure a model once, override per run - - - - +Your application: FireflyAgent or @firefly_agent +Typed inputs and outputs · run / run_sync / run_stream · configure a model once, override per run + + + + -Firefly tools -@tool · BaseTool · ToolKit -Guards and tool-call hooks -Adapted to the agent engine - +Firefly tools +@tool · BaseTool · ToolKit +Guards and tool-call hooks +Adapted to the agent engine + -Firefly memory -MemoryManager -Conversation + working memory -In-memory · file · SQLite -PostgreSQL · MongoDB - +Firefly memory +MemoryManager +Conversation + working memory +In-memory · file · SQLite +PostgreSQL · MongoDB + -Firefly model configuration -ModelOptions: typed run controls -ModelSpec / ModelFactory -Provider setup and credentials -Explicit Chat / Responses routes - +Firefly model configuration +ModelOptions: typed run controls +ModelSpec / ModelFactory +Provider setup and credentials +Explicit Chat / Responses routes + -Compose what the application needs -Reasoning patterns · pipelines and workflows · retrieval with embeddings and vector stores -Middleware · validation · observability · explainability · experiments and lab - - -Pydantic AI 2 engine -Provider clients · model/tool exchange · structured output · streaming (subject to model and API support) -Configuration, storage, resilience and security support these capabilities across the framework. +Compose what the application needs +Reasoning patterns · pipelines and workflows · retrieval with embeddings and vector stores +Middleware · validation · observability · explainability · experiments and lab + + +Pydantic AI 2 engine +Provider clients · model/tool exchange · structured output · streaming (subject to model and API support) +Configuration, storage, resilience and security support these capabilities across the framework. diff --git a/docs/assets/banner-light.svg b/docs/assets/banner-light.svg new file mode 100644 index 00000000..db465f77 --- /dev/null +++ b/docs/assets/banner-light.svg @@ -0,0 +1 @@ +agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file diff --git a/docs/assets/banner.svg b/docs/assets/banner.svg index d30af40b..a2558904 100644 --- a/docs/assets/banner.svg +++ b/docs/assets/banner.svg @@ -1,38 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - agentic - - - Production-grade agents, reasoning & pipelines - type-safe · model-agnostic · built on Pydantic AI · async-native - fireflyframework-agentic - +agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file diff --git a/docs/assets/brand-logo-light.svg b/docs/assets/brand-logo-light.svg new file mode 100644 index 00000000..e22f3bb6 --- /dev/null +++ b/docs/assets/brand-logo-light.svg @@ -0,0 +1 @@ +agentic by Firefly \ No newline at end of file diff --git a/docs/assets/brand-logo.svg b/docs/assets/brand-logo.svg index 4f77bd54..76b129ec 100644 --- a/docs/assets/brand-logo.svg +++ b/docs/assets/brand-logo.svg @@ -1,9 +1 @@ - - Firefly Agentic - Firefly wordmark with the amber glow and Agentic name on a dark violet background. - - - - - agentic - +agentic by Firefly \ No newline at end of file diff --git a/docs/assets/ecosystem.svg b/docs/assets/ecosystem.svg index b13321d5..b9bcb8ed 100644 --- a/docs/assets/ecosystem.svg +++ b/docs/assets/ecosystem.svg @@ -1,62 +1,62 @@ The Firefly family includes Java and Spring Boot, .NET, Python PyFly, Rust, Go, Angular frontend, and Agentic for agents, reasoning, and retrievalThe Firefly family includes Java and Spring Boot, .NET, Python PyFly, Rust, Go, Angular frontend, and Agentic for agents, reasoning, and retrieval. Each project has its own APIs and lifecycle; the diagram does not imply universal feature parity. - - - - - - - - - - - - - - - - The Firefly family - fireflyframework-agentic - - Related projects for application services, frontends and agentic systems. - - - - - - - - - -FRAMEWORK - + + + + + + + + + + + + + + + agentic by Firefly + The Firefly family + fireflyframework-agentic + + Related projects for application services, frontends and agentic systems. + + + + + + + + +Firefly +FRAMEWORK + -Java / Spring Boot -Application services - +Java / Spring Boot +Application services + -.NET -Application services - +.NET +Application services + -PyFly -Python application services - +PyFly +Python application services + -Rust -Async application services - +Rust +Async application services + -Go -Developer tooling - +Go +Developer tooling + -Frontend -Angular · flyfront - - +Frontend +Angular · flyfront + + Agentic -Agents · reasoning · retrieval -A shared family identity; each project documents its own APIs, features and lifecycle. +Agents · reasoning · retrieval +A shared family identity; each project documents its own APIs, features and lifecycle. diff --git a/docs/assets/favicon.svg b/docs/assets/favicon.svg index 600f3d0f..942de307 100644 --- a/docs/assets/favicon.svg +++ b/docs/assets/favicon.svg @@ -1,22 +1 @@ - - - - - - - - - - - - - - - - - - - - - - +agentic diff --git a/docs/assets/fonts/Manrope-variable.woff2 b/docs/assets/fonts/Manrope-variable.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..71eb731d558046199aa7f985adbf812890a093a1 GIT binary patch literal 24836 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 literal 0 HcmV?d00001 diff --git a/docs/assets/fonts/OFL.txt b/docs/assets/fonts/OFL.txt new file mode 100644 index 00000000..462280f3 --- /dev/null +++ b/docs/assets/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2019 The Manrope Project Authors (https://github.com/sharanda/manrope) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/assets/logo.svg b/docs/assets/logo.svg index 1fe31a05..76b129ec 100644 --- a/docs/assets/logo.svg +++ b/docs/assets/logo.svg @@ -1,25 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - +agentic by Firefly \ No newline at end of file diff --git a/docs/assets/model-routing.svg b/docs/assets/model-routing.svg index 11da75bc..f539b756 100644 --- a/docs/assets/model-routing.svg +++ b/docs/assets/model-routing.svg @@ -1,62 +1,62 @@ Model routing through FireflyAgentModel routing through FireflyAgent. Resolve the effective model, merge typed ModelOptions, validate against the model profile, and translate to native settings. Firefly preserves legacy openai and azure aliases as Chat Completions; openai-responses and azure-responses explicitly select Responses. Other providers use their own adapters. Existing model objects retain their class and client. Support depends on the selected model and API, and unsupported explicit controls raise ModelOptionsError. - - - - - - - - - - - - - - - - One application API, explicit model routes - fireflyframework-agentic - - Keep agent behavior in Firefly; select the provider and API deliberately. - + + + + + + + + + + + + + + + agentic by Firefly + One application API, explicit model routes + fireflyframework-agentic + + Keep agent behavior in Firefly; select the provider and API deliberately. + -FireflyAgent / @firefly_agent -Firefly tools + MemoryManager + ModelOptions - - +FireflyAgent / @firefly_agent +Firefly tools + MemoryManager + ModelOptions + + -Resolve the effective model and validate typed options -Configured model or per-run override; preserve an existing model object's class and client. -Merge ModelOptions, validate against the model/profile, then translate to native request settings. - - - - - - +Resolve the effective model and validate typed options +Configured model or per-run override; preserve an existing model object's class and client. +Merge ModelOptions, validate against the model/profile, then translate to native request settings. + + + + + + -Chat Completions -openai: · openai-chat: -azure: · azure-chat: -Legacy aliases keep Chat -OpenAI / Azure Chat API - +Chat Completions +openai: · openai-chat: +azure: · azure-chat: +Legacy aliases keep Chat +OpenAI / Azure Chat API + -Responses -openai-responses: -azure-responses: -Explicit Responses selection -OpenAI / Azure Responses API - +Responses +openai-responses: +azure-responses: +Explicit Responses selection +OpenAI / Azure Responses API + -Other model providers -For example: Anthropic, Google -Provider-specific adapters -ModelSpec / ModelFactory -support configured clients -Per-run fields override agent options; explicit None clears an inherited field. -Unsupported explicit controls fail early with ModelOptionsError. Feature support varies by model and API. -Advanced escape hatch: native model_settings; they do not change the selected API route. +Other model providers +For example: Anthropic, Google +Provider-specific adapters +ModelSpec / ModelFactory +support configured clients +Per-run fields override agent options; explicit None clears an inherited field. +Unsupported explicit controls fail early with ModelOptionsError. Feature support varies by model and API. +Advanced escape hatch: native model_settings; they do not change the selected API route. diff --git a/docs/assets/pipeline.svg b/docs/assets/pipeline.svg index 7dbe7334..7d7fdf89 100644 --- a/docs/assets/pipeline.svg +++ b/docs/assets/pipeline.svg @@ -1,79 +1,79 @@ An example document-processing DAG ingests and splits, classifies, extracts in parallel, validates, assembles, and explainsAn example document-processing DAG ingests and splits, classifies, extracts in parallel, validates, assembles, and explains. It illustrates an application composition rather than mandatory stages. PipelineBuilder and PipelineEngine also support explicitly enabled cycles with visit limits. Pause requests external input; Send dispatches worker payloads. Checkpointing and audit/event sinks are configurable. - - - - - - - - - - - - - - - - Pipelines: declarative graphs and explicit state - fireflyframework-agentic - - Build a DAG for parallel stages, or enable cyclic routing for iterative work. -EXAMPLE: DOCUMENT PROCESSING DAG - + + + + + + + + + + + + + + + agentic by Firefly + Pipelines: declarative graphs and explicit state + fireflyframework-agentic + + Build a DAG for parallel stages, or enable cyclic routing for iterative work. +EXAMPLE: DOCUMENT PROCESSING DAG + -Ingest and split -BinaryNormalizer -DocumentSplitter - +Ingest and split +BinaryNormalizer +DocumentSplitter + -Classify -AgentStep -Typed document category - +Classify +AgentStep +Typed document category + -Extract in parallel -Send dispatches worker nodes -Reducers merge worker results - +Extract in parallel +Send dispatches worker nodes +Reducers merge worker results + -Validate -OutputReviewer -Application validation rules - +Validate +OutputReviewer +Application validation rules + -Assemble -Typed application output -Merge validated fields - +Assemble +Typed application output +Merge validated fields + -Explain -ReportBuilder -Build the processing report - - - - - - +Explain +ReportBuilder +Build the processing report + + + + + + -Control flow -Pause: wait for external input -Send: dispatch worker payloads -Cycles: opt in + visit limits - +Control flow +Pause: wait for external input +Send: dispatch worker payloads +Cycles: opt in + visit limits + -Checkpointing -Checkpointer / FileCheckpointer -Persist resumable run state -Resume from saved checkpoints - +Checkpointing +Checkpointer / FileCheckpointer +Persist resumable run state +Resume from saved checkpoints + -Audit and events -AuditLog records node results -Event handlers observe progress -Wire the sinks your app needs -PipelineBuilder + PipelineEngine · per-node conditions, retries and timeouts -The flow above is one application design; these stages are not a required pipeline sequence. +Audit and events +AuditLog records node results +Event handlers observe progress +Wire the sinks your app needs +PipelineBuilder + PipelineEngine · per-node conditions, retries and timeouts +The flow above is one application design; these stages are not a required pipeline sequence. diff --git a/docs/assets/protocols.svg b/docs/assets/protocols.svg index d639ee84..afb7be10 100644 --- a/docs/assets/protocols.svg +++ b/docs/assets/protocols.svg @@ -1,67 +1,67 @@ Selected Firefly extension contracts for agents, tools, models, reasoning, memory, content, retrieval, pipelines, and workflowsSelected Firefly extension contracts for agents, tools, models, reasoning, memory, content, retrieval, pipelines, and workflows. Protocol conformance describes a structural contract, not automatic registration. Abstract base classes provide subclass extension points. ModelOptions is typed configuration rather than a protocol. - - - - - - - - - - - - - - - - Extension contracts - fireflyframework-agentic - - Selected public protocols, grouped by responsibility; use the matching constructor, adapter or registry. - + + + + + + + + + + + + + + + agentic by Firefly + Extension contracts + fireflyframework-agentic + + Selected public protocols, grouped by responsibility; use the matching constructor, adapter or registry. + -Agents and tools -AgentLike · ToolProtocol -AgentMiddleware -GuardProtocol · ToolCallListener - +Agents and tools +AgentLike · ToolProtocol +AgentMiddleware +GuardProtocol · ToolCallListener + -Models and reasoning -CredentialResolver -ReasoningPattern -ValidationRule - +Models and reasoning +CredentialResolver +ReasoningPattern +ValidationRule + -Memory and content -MemoryStore · ContentSource -Chunker · CompressionStrategy -OfficeConverter - +Memory and content +MemoryStore · ContentSource +Chunker · CompressionStrategy +OfficeConverter + -Retrieval -EmbeddingProtocol -VectorStoreProtocol -ScopedVectorStore - +Retrieval +EmbeddingProtocol +VectorStoreProtocol +ScopedVectorStore + -Pipelines -StepExecutor · Checkpointer -AuditLog · QueryableAuditLog -EventHandler -PipelineEventHandler - +Pipelines +StepExecutor · Checkpointer +AuditLog · QueryableAuditLog +EventHandler +PipelineEventHandler + -Workflows -AgentRunner -StreamingAgentRunner -JournalBackend -ModelSelectionStrategy - +Workflows +AgentRunner +StreamingAgentRunner +JournalBackend +ModelSelectionStrategy + -Protocols and base classes have different roles -Protocols describe structural contracts. ABCs such as BaseTool, BaseEmbedder, BaseVectorStore -and StorageBackend provide explicit subclass extension points; matching a protocol does not register it. -ModelOptions is a typed configuration model, not an extension protocol. +Protocols and base classes have different roles +Protocols describe structural contracts. ABCs such as BaseTool, BaseEmbedder, BaseVectorStore +and StorageBackend provide explicit subclass extension points; matching a protocol does not register it. +ModelOptions is a typed configuration model, not an extension protocol. diff --git a/docs/assets/rag.svg b/docs/assets/rag.svg index 376d289c..0cc2c1c2 100644 --- a/docs/assets/rag.svg +++ b/docs/assets/rag.svg @@ -1,65 +1,65 @@ Firefly retrieval supports eight embedding providers and six vector-store backends behind EmbeddingProtocol and VectorStoreProtocolFirefly retrieval supports eight embedding providers and six vector-store backends behind EmbeddingProtocol and VectorStoreProtocol. Documents are upserted, text queries return SearchResult objects, and applications pass retrieved context to FireflyAgent. Automatic embedding and search_text require an attached embedder. Indexing and queries must use compatible embedding dimensions and the same embedding space; filtering and persistence vary by backend. - - - - - - - - - - - - - - - - Retrieval: a shared API for embeddings and vector stores - fireflyframework-agentic - - Select compatible embedding dimensions, provider configuration and backend behavior. - + + + + + + + + + + + + + + + agentic by Firefly + Retrieval: a shared API for embeddings and vector stores + fireflyframework-agentic + + Select compatible embedding dimensions, provider configuration and backend behavior. + -Embedding providers -OpenAI · Azure OpenAI -Cohere · Google -Mistral · Voyage AI -AWS Bedrock · Ollama - -EmbeddingProtocol -BaseEmbedder - +Embedding providers +OpenAI · Azure OpenAI +Cohere · Google +Mistral · Voyage AI +AWS Bedrock · Ollama + +EmbeddingProtocol +BaseEmbedder + -Vector store backends -InMemoryVectorStore -ChromaDB · Pinecone -Qdrant · pgvector -sqlite-vec - -VectorStoreProtocol -BaseVectorStore - +Vector store backends +InMemoryVectorStore +ChromaDB · Pinecone +Qdrant · pgvector +sqlite-vec + +VectorStoreProtocol +BaseVectorStore + -Index documents -VectorDocument -> upsert() - - +Index documents +VectorDocument -> upsert() + + -Search -search_text(query, top_k=5) - - +Search +search_text(query, top_k=5) + + -Use retrieved context -SearchResult -> FireflyAgent - - - +Use retrieved context +SearchResult -> FireflyAgent + + + -Compose retrieval with the rest of Firefly -An attached embedder enables automatic document embedding and search_text(). -TenantScopedVectorStore scopes namespaces; EmbeddingStep and RetrievalStep integrate with pipelines. -Indexing and querying must use the same embedding space. Backend filtering and persistence can differ. +Compose retrieval with the rest of Firefly +An attached embedder enables automatic document embedding and search_text(). +TenantScopedVectorStore scopes namespaces; EmbeddingStep and RetrievalStep integrate with pipelines. +Indexing and querying must use the same embedding space. Backend filtering and persistence can differ. diff --git a/docs/assets/reasoning.svg b/docs/assets/reasoning.svg index a6245294..6d204511 100644 --- a/docs/assets/reasoning.svg +++ b/docs/assets/reasoning.svg @@ -1,71 +1,71 @@ Six reasoning patterns share result and trace contractsSix reasoning patterns share result and trace contracts. ReAct, Chain of Thought, Plan-and-Execute, and Reflexion use the AbstractReasoningPattern template: reason, act, observe, and should_continue, with early stopping and iteration limits. Tree of Thoughts overrides execute to generate and score branches; Goal Decomposition overrides execute to coordinate phases and tasks. ReasoningPipeline composes patterns. - - - - - - - - - - - - - - - - Six reasoning patterns, shared contracts - fireflyframework-agentic - - Four patterns use the base template below; Tree of Thoughts and Goal Decomposition override execute(). - + + + + + + + + + + + + + + + agentic by Firefly + Six reasoning patterns, shared contracts + fireflyframework-agentic + + Four patterns use the base template below; Tree of Thoughts and Goal Decomposition override execute(). + -_reason - - +_reason + + -_act - - +_act + + -_observe - - +_observe + + -_should_continue - -Base template: ReAct · Chain of Thought · Plan-and-Execute · Reflexion - +_should_continue + +Base template: ReAct · Chain of Thought · Plan-and-Execute · Reflexion + -ReAct -Think, call a tool, observe -Interleaved reasoning and action - +ReAct +Think, call a tool, observe +Interleaved reasoning and action + -Chain of Thought -Structured intermediate steps -A final answer from those steps - +Chain of Thought +Structured intermediate steps +A final answer from those steps + -Plan-and-Execute -Create a plan, execute its steps -Replan when configured - +Plan-and-Execute +Create a plan, execute its steps +Replan when configured + -Reflexion -Execute, critique, retry -Use feedback on another attempt - +Reflexion +Execute, critique, retry +Use feedback on another attempt + -Tree of Thoughts -Generate and evaluate branches -Select the highest-scored branch - +Tree of Thoughts +Generate and evaluate branches +Select the highest-scored branch + -Goal Decomposition -Split a goal into sub-goals -Coordinate their execution -All return ReasoningResult with a trace; ReasoningPipeline composes patterns. +Goal Decomposition +Split a goal into sub-goals +Coordinate their execution +All return ReasoningResult with a trace; ReasoningPipeline composes patterns. diff --git a/docs/assets/workflows.svg b/docs/assets/workflows.svg index b05be48d..2497a723 100644 --- a/docs/assets/workflows.svg +++ b/docs/assets/workflows.svg @@ -1,63 +1,63 @@ Code-defined workflows use the workflow decorator and native Python control flowCode-defined workflows use the workflow decorator and native Python control flow. subworkflow is a callable primitive, not a decorator. WorkflowContext carries a runner, journal, budget, arguments, and events. FireflyAgentRunner is the default. Journal replay can reuse completed call results but does not make new model responses or arbitrary side effects deterministic. Verification helpers can evaluate outputs. - - - - - - - - - - - - - - - - Workflows: Python control flow around your agents - fireflyframework-agentic - - Use @workflow for code-defined orchestration; call run_workflow() or await the decorated workflow. - + + + + + + + + + + + + + + + agentic by Firefly + Workflows: Python control flow around your agents + fireflyframework-agentic + + Use @workflow for code-defined orchestration; call run_workflow() or await the decorated workflow. + -Your async workflow function -Native conditionals and loops; subworkflow() invokes another workflow. - - +Your async workflow function +Native conditionals and loops; subworkflow() invokes another workflow. + + -Workflow primitives -agent() · parallel() · pipeline() · stream() -phase() · human() · map_agents() · log() - - -WorkflowContext -current_workflow() carries the runner, journal, budget, arguments and events. - - +Workflow primitives +agent() · parallel() · pipeline() · stream() +phase() · human() · map_agents() · log() + + +WorkflowContext +current_workflow() carries the runner, journal, budget, arguments and events. + + -Runner -FireflyAgentRunner is the default -DefaultAgentRunner is optional -SmartRoutingRunner can select -models through routing strategies - - +Runner +FireflyAgentRunner is the default +DefaultAgentRunner is optional +SmartRoutingRunner can select +models through routing strategies + + -Journal -Completed calls can be replayed -FileJournalBackend persists runs -Resume uses recorded call results -External side effects need care - - +Journal +Completed calls can be replayed +FileJournalBackend persists runs +Resume uses recorded call results +External side effects need care + + -WorkflowBudget -Concurrent and total agents -Token and cost ceilings -Wall-clock timeout -Configure ceilings for your run -Verification helpers: cascade · adversarial_verify · judge_panel · loop_until_dry -Journal replay does not make fresh model calls or arbitrary Python side effects deterministic. +WorkflowBudget +Concurrent and total agents +Token and cost ceilings +Wall-clock timeout +Configure ceilings for your run +Verification helpers: cascade · adversarial_verify · judge_panel · loop_until_dry +Journal replay does not make fresh model calls or arbitrary Python side effects deterministic. diff --git a/docs/javascripts/constellation.js b/docs/javascripts/constellation.js index 33d6cc40..eae536a2 100644 --- a/docs/javascripts/constellation.js +++ b/docs/javascripts/constellation.js @@ -1,7 +1,7 @@ /* * Firefly constellation — the landing-page signature. * Amber fireflies drift through the dark; when they pass near one another a - * faint violet edge is drawn between them. Read it two ways at once: fireflies + * faint stone edge is drawn between them. Read it two ways at once: fireflies * in the night, and a network of agents delegating. One ambient animation, * nothing else moves. * @@ -57,7 +57,7 @@ var dx = a.x - b.x, dy = a.y - b.y; var d = Math.sqrt(dx * dx + dy * dy); if (d < LINK) { - ctx.strokeStyle = "rgba(167,139,250," + (1 - d / LINK) * 0.22 + ")"; + ctx.strokeStyle = "rgba(191,184,171," + (1 - d / LINK) * 0.22 + ")"; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(a.x, a.y); @@ -77,14 +77,14 @@ } var tw = reduce ? 0.85 : 0.55 + 0.45 * Math.sin(t * 0.001 + n.p); var halo = ctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, n.r * 6); - halo.addColorStop(0, "rgba(255,249,193," + 0.9 * tw + ")"); - halo.addColorStop(0.4, "rgba(246,168,33," + 0.5 * tw + ")"); - halo.addColorStop(1, "rgba(246,128,0,0)"); + halo.addColorStop(0, "rgba(255,206,130," + 0.9 * tw + ")"); + halo.addColorStop(0.4, "rgba(255,179,74," + 0.5 * tw + ")"); + halo.addColorStop(1, "rgba(255,179,74,0)"); ctx.fillStyle = halo; ctx.beginPath(); ctx.arc(n.x, n.y, n.r * 6, 0, 6.2832); ctx.fill(); - ctx.fillStyle = "rgba(255,253,240," + 0.95 * tw + ")"; + ctx.fillStyle = "rgba(243,241,235," + 0.95 * tw + ")"; ctx.beginPath(); ctx.arc(n.x, n.y, n.r * 0.9, 0, 6.2832); ctx.fill(); diff --git a/docs/stylesheets/firefly.css b/docs/stylesheets/firefly.css index d47c6875..327b61f0 100644 --- a/docs/stylesheets/firefly.css +++ b/docs/stylesheets/firefly.css @@ -1,44 +1,44 @@ /* ============================================================================= Firefly Agentic — brand stylesheet Loaded site-wide. Two responsibilities, kept separate: - 1. Docs theme: recolor Material to the exact violet brand (both schemes). + 1. Docs theme: recolor Material to the Framework palette (both schemes). 2. Landing page: the immersive "firefly-in-the-dark" home, scoped under .ff-home so nothing leaks into the docs. Brand tokens are lifted verbatim from assets/README.md. ========================================================================== */ -@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"); +@font-face { font-family: "Manrope"; font-style: normal; font-weight: 200 800; font-display: swap; src: url("../assets/fonts/Manrope-variable.woff2") format("woff2"); } :root { - /* Night sky */ - --ff-sky-0: #0b0a14; - --ff-sky-1: #120d1c; - --ff-sky-2: #140f1e; - --ff-ink: #1e1633; - /* Violet system */ - --ff-violet: #8b5cf6; - --ff-violet-bright: #a78bfa; - --ff-violet-2: #7c3aed; - --ff-violet-deep: #4c1d95; - --ff-violet-pale: #d6c6ff; - /* The one warm spark — the shared firefly */ - --ff-amber: #f6a821; - --ff-amber-hot: #f68000; - --ff-amber-pale: #fff9c1; + /* Framework charcoal */ + --ff-sky-0: #10110f; + --ff-sky-1: #191b16; + --ff-sky-2: #20221c; + --ff-ink: #10110f; + /* Amber and graphite */ + --ff-accent: #ffb34a; + --ff-accent-bright: #ffce82; + --ff-accent-2: #ffb34a; + --ff-accent-deep: #272820; + --ff-accent-pale: #f3f1eb; + /* Original Firefly amber */ + --ff-amber: #ffb34a; + --ff-amber-hot: #ffb34a; + --ff-amber-pale: #ffce82; /* Text on dark */ - --ff-fg: #ece8f5; - --ff-muted: #b3a9cd; - --ff-faint: #8b82a3; + --ff-fg: #f3f1eb; + --ff-muted: #bfb8ab; + --ff-faint: #a5a697; /* Surfaces */ - --ff-card: rgba(139, 92, 246, 0.05); - --ff-card-2: rgba(167, 139, 250, 0.08); - --ff-card-bd: rgba(167, 139, 250, 0.16); - --ff-card-bd-hot: rgba(167, 139, 250, 0.42); + --ff-card: rgba(191, 184, 171, 0.05); + --ff-card-2: rgba(191, 184, 171, 0.08); + --ff-card-bd: rgba(191, 184, 171, 0.16); + --ff-card-bd-hot: rgba(191, 184, 171, 0.42); /* Gradients */ - --ff-wm: linear-gradient(92deg, #d6c6ff 0%, #a78bfa 48%, #7c3aed 100%); - --ff-amber-grad: radial-gradient(circle at 50% 42%, #fffdf0, #fff6b0 45%, #f68000 100%); + --ff-wm: linear-gradient(92deg, #f3f1eb 0%, #ffce82 48%, #ffb34a 100%); + --ff-amber-grad: radial-gradient(circle at 50% 42%, #f3f1eb, #ffce82 45%, #ffb34a 100%); --ff-header-h: 2.9rem; - --ff-display: "Space Grotesk", "Inter", system-ui, sans-serif; + --ff-display: "Manrope", system-ui, sans-serif; } /* ============================================================================= @@ -46,22 +46,23 @@ ========================================================================== */ [data-md-color-scheme="default"] { - --md-primary-fg-color: #6d28d9; - --md-primary-fg-color--light: #8b5cf6; - --md-primary-fg-color--dark: #5b21b6; - --md-accent-fg-color: #7c3aed; - --md-typeset-a-color: #7c3aed; + --md-primary-fg-color: #10110f; + --md-primary-fg-color--light: #272820; + --md-primary-fg-color--dark: #10110f; + --md-accent-fg-color: #855414; + --md-typeset-a-color: #855414; + --md-default-bg-color: #f3f1eb; } -/* Slate, tinted toward violet so the dark docs feel like the same night sky. */ +/* Slate, tinted toward neutral so the dark docs feel like the same night sky. */ [data-md-color-scheme="slate"] { - --md-hue: 264; - --md-primary-fg-color: #1c142e; - --md-primary-fg-color--light: #2a1f45; - --md-primary-fg-color--dark: #140e22; - --md-accent-fg-color: #a78bfa; - --md-typeset-a-color: #b89cff; - --md-default-bg-color: hsla(264, 24%, 9%, 1); + --md-hue: 80; + --md-primary-fg-color: #10110f; + --md-primary-fg-color--light: #272820; + --md-primary-fg-color--dark: #10110f; + --md-accent-fg-color: #ffce82; + --md-typeset-a-color: #ffb34a; + --md-default-bg-color: #10110f; } /* Display face for all headings, in docs and on the landing. */ @@ -99,14 +100,14 @@ body:has(.ff-home) .md-header { transition: background-color 0.3s ease, box-shadow 0.3s ease; } body:has(.ff-home) .md-header--shadow { - background-color: rgba(11, 10, 20, 0.82); + background-color: rgba(16, 17, 15, 0.82); backdrop-filter: blur(10px); - box-shadow: 0 1px 0 rgba(167, 139, 250, 0.14); + box-shadow: 0 1px 0 rgba(191, 184, 171, 0.14); } .ff-home { color: var(--ff-fg); - font-family: "Inter", system-ui, sans-serif; + font-family: "Manrope", system-ui, sans-serif; font-size: 16px; line-height: 1.6; overflow: hidden; /* contain the hero glows */ @@ -129,7 +130,7 @@ body:has(.ff-home) .md-header--shadow { font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; - color: var(--ff-violet-bright); + color: var(--ff-accent-bright); margin: 0 0 1.1rem; } @@ -156,15 +157,15 @@ body:has(.ff-home) .md-header--shadow { z-index: -2; display: block; } -.ff-hero::before { /* layered violet ambient, echoing the banner */ +.ff-hero::before { /* layered neutral ambient, echoing the banner */ content: ""; position: absolute; inset: -20% -10% 0; z-index: -1; background: - radial-gradient(60% 55% at 22% 18%, rgba(124, 58, 237, 0.28), transparent 60%), - radial-gradient(60% 55% at 82% 10%, rgba(99, 102, 241, 0.22), transparent 60%), - radial-gradient(45% 40% at 50% 90%, rgba(76, 29, 149, 0.30), transparent 70%); + radial-gradient(60% 55% at 22% 18%, rgba(255, 179, 74, 0.28), transparent 60%), + radial-gradient(60% 55% at 82% 10%, rgba(191, 184, 171, 0.22), transparent 60%), + radial-gradient(45% 40% at 50% 90%, rgba(98, 100, 91, 0.30), transparent 70%); pointer-events: none; } @@ -186,8 +187,8 @@ body:has(.ff-home) .md-header--shadow { .ff-hero__lead code { font-family: "JetBrains Mono", monospace; font-size: 0.92em; - color: var(--ff-violet-pale); - background: rgba(167, 139, 250, 0.12); + color: var(--ff-accent-pale); + background: rgba(191, 184, 171, 0.12); padding: 0.08em 0.4em; border-radius: 0.3rem; } @@ -201,7 +202,7 @@ body:has(.ff-home) .md-header--shadow { font-family: "JetBrains Mono", monospace; font-size: 0.84rem; color: var(--ff-fg); - background: rgba(20, 15, 30, 0.72); + background: rgba(32, 34, 28, 0.72); border: 1px solid var(--ff-card-bd); border-radius: 0.6rem; padding: 0.65rem 0.65rem 0.65rem 1rem; @@ -225,12 +226,12 @@ body:has(.ff-home) .md-header--shadow { width: 2rem; height: 2rem; border: 0; border-radius: 0.4rem; - background: rgba(167, 139, 250, 0.14); - color: var(--ff-violet-bright); + background: rgba(191, 184, 171, 0.14); + color: var(--ff-accent-bright); cursor: pointer; transition: background 0.2s, color 0.2s; } -.ff-install__copy:hover { background: rgba(167, 139, 250, 0.28); color: #fff; } +.ff-install__copy:hover { background: rgba(191, 184, 171, 0.28); color: #fff; } .ff-install__copy svg { width: 1rem; height: 1rem; } .ff-install__copy.is-copied { background: rgba(111, 207, 114, 0.22); color: #6fcf72; } .ff-install__copy.is-copied svg { display: none; } @@ -257,17 +258,17 @@ body:has(.ff-home) .md-header--shadow { } .ff-btn svg { width: 1.05rem; height: 1.05rem; } .ff-btn--primary { - color: #fff; - background: linear-gradient(180deg, #8b5cf6, #7c3aed); - box-shadow: 0 10px 28px rgba(124, 58, 237, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.2); + color: #10110f; + background: #ffb34a; + box-shadow: 0 10px 28px rgba(255, 179, 74, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.2); } -.ff-btn--primary:hover { transform: translateY(-2px); box-shadow: 0 16px 40px rgba(124, 58, 237, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.25); } +.ff-btn--primary:hover { transform: translateY(-2px); box-shadow: 0 16px 40px rgba(255, 179, 74, 0.24), inset 0 1px 0 rgba(255, 255, 255, 0.25); } .ff-btn--ghost { color: var(--ff-fg); - background: rgba(167, 139, 250, 0.06); + background: rgba(191, 184, 171, 0.06); border-color: var(--ff-card-bd); } -.ff-btn--ghost:hover { background: rgba(167, 139, 250, 0.16); border-color: var(--ff-card-bd-hot); transform: translateY(-2px); } +.ff-btn--ghost:hover { background: rgba(191, 184, 171, 0.16); border-color: var(--ff-card-bd-hot); transform: translateY(-2px); } /* ---- Trust bar --------------------------------------------------------- */ .ff-trust { @@ -287,14 +288,14 @@ body:has(.ff-home) .md-header--shadow { border-radius: 999px; padding: 0.38rem 0.9rem; } -.ff-chip b { color: var(--ff-violet-bright); font-weight: 700; } -.ff-chip--amber { color: #ffce7a; } +.ff-chip b { color: var(--ff-accent-bright); font-weight: 700; } +.ff-chip--amber { color: #ffce82; } .ff-chip--amber b { color: var(--ff-amber); } /* ---- Section scaffold -------------------------------------------------- */ .ff-section { padding-block: 4.5rem; position: relative; } .ff-section--tint { - background: linear-gradient(180deg, transparent, rgba(124, 58, 237, 0.05) 40%, transparent); + background: linear-gradient(180deg, transparent, rgba(255, 179, 74, 0.05) 40%, transparent); } .ff-section__head { max-width: 62ch; margin: 0 auto 2.6rem; text-align: center; } .ff-section__kicker { @@ -342,9 +343,9 @@ body:has(.ff-home) .md-header--shadow { width: 0.55rem; height: 0.55rem; border-radius: 50%; background: var(--ff-amber-grad); - box-shadow: 0 0 10px 1px rgba(246, 168, 33, 0.6); + box-shadow: 0 0 10px 1px rgba(255, 179, 74, 0.6); } -.ff-why__list b { color: var(--ff-violet-bright); font-weight: 600; } +.ff-why__list b { color: var(--ff-accent-bright); font-weight: 600; } /* ---- Feature grid ------------------------------------------------------ */ .ff-grid { @@ -369,7 +370,7 @@ body:has(.ff-home) .md-header--shadow { border-radius: 50%; background: var(--ff-amber-grad); opacity: 0.5; - box-shadow: 0 0 8px 1px rgba(246, 168, 33, 0.5); + box-shadow: 0 0 8px 1px rgba(255, 179, 74, 0.5); transition: opacity 0.2s ease, box-shadow 0.2s ease; } .ff-feat:hover { @@ -377,7 +378,7 @@ body:has(.ff-home) .md-header--shadow { border-color: var(--ff-card-bd-hot); background: var(--ff-card-2); } -.ff-feat:hover::after { opacity: 1; box-shadow: 0 0 14px 2px rgba(246, 168, 33, 0.8); } +.ff-feat:hover::after { opacity: 1; box-shadow: 0 0 14px 2px rgba(255, 179, 74, 0.8); } .ff-feat__name { font-family: var(--ff-display); font-weight: 600; @@ -389,7 +390,7 @@ body:has(.ff-home) .md-header--shadow { /* ---- Diagram frame ----------------------------------------------------- */ .ff-figure { - background: rgba(245, 242, 254, 0.96); + background: rgba(243, 241, 235, 0.96); border: 1px solid var(--ff-card-bd); border-radius: 1rem; padding: 1.4rem; @@ -397,10 +398,10 @@ body:has(.ff-home) .md-header--shadow { overflow: hidden; } .ff-install-note { color: var(--ff-muted); font-size: 0.85rem; } -.ff-install-note a { color: var(--ff-violet-bright); text-decoration: underline; } -.ff-figure .ff-figcap { color: #52416d; } -.ff-figure .ff-figcap a { color: #6033ac; text-decoration: underline; } -.ff-figure a:focus-visible { outline: 3px solid #7c3aed; outline-offset: 4px; } +.ff-install-note a { color: var(--ff-accent-bright); text-decoration: underline; } +.ff-figure .ff-figcap { color: #62645b; } +.ff-figure .ff-figcap a { color: #855414; text-decoration: underline; } +.ff-figure a:focus-visible { outline: 3px solid #ffb34a; outline-offset: 4px; } .ff-figure img { display: block; width: 100%; height: auto; } .ff-figure--pair { display: grid; grid-template-columns: 1fr; gap: 1.4rem; background: none; border: 0; box-shadow: none; padding: 0; } .ff-figure--pair > .ff-figure { margin: 0; } @@ -444,7 +445,7 @@ body:has(.ff-home) .md-header--shadow { } .ff-tabs__labels label:hover { color: var(--ff-fg); } .ff-window { - background: #0e0b18; + background: #151611; border: 1px solid var(--ff-card-bd); border-radius: 0.8rem; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5); @@ -455,11 +456,11 @@ body:has(.ff-home) .md-header--shadow { align-items: center; gap: 0.45rem; padding: 0.7rem 1rem; - border-bottom: 1px solid rgba(167, 139, 250, 0.12); + border-bottom: 1px solid rgba(191, 184, 171, 0.12); } .ff-window__bar i { width: 0.62rem; height: 0.62rem; border-radius: 50%; display: inline-block; } .ff-window__bar i:nth-child(1) { background: #f6705a; } -.ff-window__bar i:nth-child(2) { background: #f6a821; } +.ff-window__bar i:nth-child(2) { background: #ffb34a; } .ff-window__bar i:nth-child(3) { background: #6fcf72; } .ff-window__file { margin-left: 0.6rem; font-family: "JetBrains Mono", monospace; font-size: 0.78rem; color: var(--ff-faint); } .ff-panel { display: none; margin: 0; } @@ -469,16 +470,16 @@ body:has(.ff-home) .md-header--shadow { font-family: "JetBrains Mono", monospace; font-size: 0.86rem; line-height: 1.7; - color: #d8d2ea; + color: #f3f1eb; overflow-x: auto; tab-size: 4; } -.ff-code .k { color: #c4a8ff; } /* keyword */ -.ff-code .d { color: #f6a821; } /* decorator */ -.ff-code .s { color: #ffce7a; } /* string */ +.ff-code .k { color: #ffce82; } /* keyword */ +.ff-code .d { color: #ffb34a; } /* decorator */ +.ff-code .s { color: #ffce82; } /* string */ .ff-code .c { color: var(--ff-faint); font-style: italic; } /* comment */ .ff-code .f { color: #8be9fd; } /* call / attribute */ -.ff-code .o { color: var(--ff-violet-bright); } /* operator-ish */ +.ff-code .o { color: var(--ff-accent-bright); } /* operator-ish */ /* show the panel whose radio is checked + light its label */ #ff-c1:checked ~ .ff-window .ff-panel.p1, #ff-c2:checked ~ .ff-window .ff-panel.p2, @@ -489,10 +490,10 @@ body:has(.ff-home) .md-header--shadow { #ff-c3:checked ~ .ff-tabs__labels label[for="ff-c3"], #ff-c4:checked ~ .ff-tabs__labels label[for="ff-c4"] { color: #fff; - background: rgba(124, 58, 237, 0.28); + background: rgba(255, 179, 74, 0.28); border-color: var(--ff-card-bd-hot); } -.ff-tabs > input:focus-visible ~ .ff-tabs__labels label { outline: 2px solid var(--ff-violet-bright); outline-offset: 2px; } +.ff-tabs > input:focus-visible ~ .ff-tabs__labels label { outline: 2px solid var(--ff-accent-bright); outline-offset: 2px; } /* ---- Learn cards ------------------------------------------------------- */ .ff-learn { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; } @@ -508,25 +509,25 @@ body:has(.ff-home) .md-header--shadow { .ff-learn__eyebrow { font-family: var(--ff-display); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ff-amber); } .ff-learn__title { font-family: var(--ff-display); font-weight: 700; font-size: 1.25rem; color: var(--ff-fg); margin: 0.6rem 0 0.5rem; } .ff-learn__desc { color: var(--ff-muted); font-size: 0.92rem; margin: 0 0 0.9rem; } -.ff-learn__more { font-family: var(--ff-display); font-weight: 600; font-size: 0.88rem; color: var(--ff-violet-bright); } +.ff-learn__more { font-family: var(--ff-display); font-weight: 600; font-size: 0.88rem; color: var(--ff-accent-bright); } .ff-learn__card:hover .ff-learn__more { color: #fff; } /* ---- Footer ------------------------------------------------------------ */ .ff-foot { - border-top: 1px solid rgba(167, 139, 250, 0.14); + border-top: 1px solid rgba(191, 184, 171, 0.14); padding-block: 3rem 2.4rem; margin-top: 2rem; - background: linear-gradient(180deg, transparent, rgba(76, 29, 149, 0.12)); + background: linear-gradient(180deg, transparent, rgba(98, 100, 91, 0.12)); } .ff-foot__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 2rem; } .ff-foot__brand { display: flex; align-items: center; gap: 0.6rem; font-family: var(--ff-display); font-weight: 700; font-size: 1.15rem; color: #fff; } -.ff-foot__brand img { width: 1.7rem; height: 1.7rem; } +.ff-foot__brand img { width: 10rem; height: auto; } .ff-foot__tag { color: var(--ff-faint); font-size: 0.9rem; margin: 0.9rem 0 0; max-width: 34ch; } -.ff-foot h4 { font-family: var(--ff-display); font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ff-violet-bright); margin: 0 0 0.9rem; } +.ff-foot h4 { font-family: var(--ff-display); font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ff-accent-bright); margin: 0 0 0.9rem; } .ff-foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; } .ff-foot a { color: var(--ff-muted); font-size: 0.92rem; } .ff-foot a:hover { color: #fff; } -.ff-foot__base { border-top: 1px solid rgba(167, 139, 250, 0.1); margin-top: 2.4rem; padding-top: 1.6rem; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.6rem; color: var(--ff-faint); font-size: 0.84rem; } +.ff-foot__base { border-top: 1px solid rgba(191, 184, 171, 0.1); margin-top: 2.4rem; padding-top: 1.6rem; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.6rem; color: var(--ff-faint); font-size: 0.84rem; } /* ---- Scroll reveal --------------------------------------------------- */ /* Intentionally none: landing content is always visible regardless of JS. @@ -575,10 +576,10 @@ body:has(.ff-home) .md-header--shadow { /* The complete Agentic lockup is the home link at every viewport size. */ .md-header__button.md-logo { display: block; } -.md-header__button.md-logo img { width: 7.5rem; height: 1.6rem; } +.md-header__button.md-logo img { width: auto; height: 2.25rem; } .md-header__topic:first-child { visibility: hidden; } .md-nav__button.md-logo img { width: 9rem; height: auto; } -.md-header__button.md-logo:focus-visible { outline: 2px solid #d6c6ff; outline-offset: 3px; } +.md-header__button.md-logo:focus-visible { outline: 2px solid #f3f1eb; outline-offset: 3px; } @media screen and (max-width: 44.984375em) { .md-header__title { display: none; } .md-header__button.md-logo { margin-right: auto; } diff --git a/mkdocs.yml b/mkdocs.yml index fb7c2393..84c92d33 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -23,22 +23,22 @@ theme: icon: repo: fontawesome/brands/github font: - text: Inter + text: Manrope code: JetBrains Mono palette: # Light scheme - media: "(prefers-color-scheme: light)" scheme: default - primary: deep purple - accent: deep purple + primary: custom + accent: custom toggle: icon: material/weather-night name: Switch to dark mode # Dark scheme — the firefly-in-the-dark default - media: "(prefers-color-scheme: dark)" scheme: slate - primary: deep purple - accent: deep purple + primary: custom + accent: custom toggle: icon: material/weather-sunny name: Switch to light mode diff --git a/overrides/home.html b/overrides/home.html index 6d346c4a..17c4870d 100644 --- a/overrides/home.html +++ b/overrides/home.html @@ -24,7 +24,6 @@
-

Open source · Apache-2.0 · Built on Pydantic AI

Agents you can run in production.

Firefly Agentic is the production-grade metaframework built on Pydantic AI. @@ -325,8 +324,7 @@

Module Reference

- - Firefly Agentic + agentic by Firefly

The production-grade agentic metaframework, built on Pydantic AI. The agentic member of the Firefly Framework family.

@@ -364,7 +362,7 @@

Ecosystem

Copyright © 2026 Firefly Software Foundation — Apache-2.0 - Built on Pydantic AI + Built on Pydantic AI
From 4f6db2bd7c2d5485555c7c62fba02c80fdf23f7c Mon Sep 17 00:00:00 2001 From: Andres Contreras Date: Thu, 8 Oct 2026 19:13:17 -0700 Subject: [PATCH 2/2] Normalize SVG file endings while preserving original identity provenance --- assets/README.md | 11 ++++++--- assets/banner-light.svg | 2 +- assets/banner.svg | 2 +- assets/brand-logo-light.svg | 2 +- assets/brand-logo.svg | 2 +- assets/logo.svg | 2 +- assets/tools/brand-source/NOTICE.md | 5 +++- assets/tools/brand-source/ORIGIN.json | 24 ++++++++++++------- assets/tools/brand-source/banner-dark.svg | 2 +- assets/tools/brand-source/banner-light.svg | 2 +- assets/tools/brand-source/firefly-light.svg | 2 +- assets/tools/brand-source/logo-dark-mono.svg | 2 +- assets/tools/brand-source/logo-dark.svg | 2 +- assets/tools/brand-source/logo-light-mono.svg | 2 +- assets/tools/brand-source/logo-light.svg | 2 +- assets/tools/build_brand_assets.py | 2 +- docs/assets/banner-light.svg | 2 +- docs/assets/banner.svg | 2 +- docs/assets/brand-logo-light.svg | 2 +- docs/assets/brand-logo.svg | 2 +- docs/assets/logo.svg | 2 +- 21 files changed, 46 insertions(+), 30 deletions(-) diff --git a/assets/README.md b/assets/README.md index e6fd2cff..2bf9e66a 100644 --- a/assets/README.md +++ b/assets/README.md @@ -35,8 +35,9 @@ including the header logo and favicon. - **Wordmark:** canonical outlined masters are recorded in [`tools/brand-source/ORIGIN.json`](tools/brand-source/ORIGIN.json), including - their SHA-256 hashes and the canonical website generator hash. Generation - verifies these hashes before using the artwork. Nested endorsement dimensions + their original export and normalized vendored SHA-256 hashes, plus the + canonical website generator hash. Generation + verifies the vendored hashes before using the artwork. Nested endorsement dimensions are retained when placing a master. - **Palette:** charcoal `#10110f`, ivory `#f3f1eb`, amber `#ffb34a`, graphite `#272820`, muted text `#62645b`, and border `#d8d4ca`. Amber title bands use @@ -74,7 +75,11 @@ necessary after changes. The generator reads the verified masters from `tools/brand-source/` and brand icons from [`tools/icons.py`](tools/icons.py). To refresh the identity, export -the canonical masters, update their provenance, and regenerate. Edit diagram +the canonical masters and record their original bytes as `sourceSha256`. +Normalize only trailing LF bytes to exactly one LF (`data.rstrip(b"\n") + b"\n"`), +record the vendored bytes as `sha256`, and regenerate. The generator applies +the same EOF normalization to every output and its documentation mirror. +Edit diagram layout in [`tools/build_brand_assets.py`](tools/build_brand_assets.py), rather than editing output SVGs independently. Brand ownership terms are recorded in [`tools/brand-source/NOTICE.md`](tools/brand-source/NOTICE.md). diff --git a/assets/banner-light.svg b/assets/banner-light.svg index db465f77..76585c12 100644 --- a/assets/banner-light.svg +++ b/assets/banner-light.svg @@ -1 +1 @@ -agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file +agentic by Firefly — intelligence, composedagentic by Firefly diff --git a/assets/banner.svg b/assets/banner.svg index a2558904..fecfbbf6 100644 --- a/assets/banner.svg +++ b/assets/banner.svg @@ -1 +1 @@ -agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file +agentic by Firefly — intelligence, composedagentic by Firefly diff --git a/assets/brand-logo-light.svg b/assets/brand-logo-light.svg index e22f3bb6..d8bb60f9 100644 --- a/assets/brand-logo-light.svg +++ b/assets/brand-logo-light.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/assets/brand-logo.svg b/assets/brand-logo.svg index 76b129ec..2e38e008 100644 --- a/assets/brand-logo.svg +++ b/assets/brand-logo.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/assets/logo.svg b/assets/logo.svg index 76b129ec..2e38e008 100644 --- a/assets/logo.svg +++ b/assets/logo.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/assets/tools/brand-source/NOTICE.md b/assets/tools/brand-source/NOTICE.md index 4c8dcabf..4f7654be 100644 --- a/assets/tools/brand-source/NOTICE.md +++ b/assets/tools/brand-source/NOTICE.md @@ -7,7 +7,10 @@ software license does not grant trademark rights or permission to imply an endorsement. The canonical Agentic masters are exported from the Framework website identity -generator and preserved byte-for-byte with SHA-256 provenance in `ORIGIN.json`. +generator. Import normalizes only the trailing LF bytes to exactly one LF; +every other byte is preserved. `ORIGIN.json` records each original export's +`sourceSha256` alongside the normalized vendored file's `sha256`. The canonical +generator's own hash remains separate and unchanged. The Firefly endorsement is preserved unchanged. Manrope is licensed under the SIL Open Font License 1.1; the redistributed font and license are in `docs/assets/fonts/` at the repository root. diff --git a/assets/tools/brand-source/ORIGIN.json b/assets/tools/brand-source/ORIGIN.json index 6bf67953..b11a1d5e 100644 --- a/assets/tools/brand-source/ORIGIN.json +++ b/assets/tools/brand-source/ORIGIN.json @@ -7,31 +7,39 @@ "masters": [ { "path": "logo-dark.svg", - "sha256": "203a6c124abb229cc1609ba4423dc5560f7e02c54c1941133464fcf2053e8b3d" + "sha256": "2365a52533de0ce733baf634b235dd45e8e51306c09e442a6fb7025e438ca44e", + "sourceSha256": "203a6c124abb229cc1609ba4423dc5560f7e02c54c1941133464fcf2053e8b3d" }, { "path": "logo-light.svg", - "sha256": "8805cc50196df356692cb974120e74a9cd1f96e69f73053cf457881401c8e597" + "sha256": "b1b19a58589d032c250502c0cce02960eb0226baea3a4c0709ed75b2ffd06ee4", + "sourceSha256": "8805cc50196df356692cb974120e74a9cd1f96e69f73053cf457881401c8e597" }, { "path": "logo-dark-mono.svg", - "sha256": "94cd3e13ad0043eef734c459464942181219a7bd3ba9618f2bb953a90fd84708" + "sha256": "2f67943df5de3ee61b98691f27945cc40c80c56a1d254c2304785e3d05d190f7", + "sourceSha256": "94cd3e13ad0043eef734c459464942181219a7bd3ba9618f2bb953a90fd84708" }, { "path": "logo-light-mono.svg", - "sha256": "d678859b104adfaada14d9b648037a866ca937ec1b7bf0c029f4b68ee097a945" + "sha256": "82063a5dad97333cb2f474be8d49f2f495bbce64b96f54046040ee51bf7dda9b", + "sourceSha256": "d678859b104adfaada14d9b648037a866ca937ec1b7bf0c029f4b68ee097a945" }, { "path": "banner-dark.svg", - "sha256": "d7938754500f58f12e7f3f81dc4cafaa2ee85423730638c315916f15f1ade6ae" + "sha256": "b7e8184d9857cf7c36033de718d47907cf103dcdfbadd5794ec3fe324ccf9f95", + "sourceSha256": "d7938754500f58f12e7f3f81dc4cafaa2ee85423730638c315916f15f1ade6ae" }, { "path": "banner-light.svg", - "sha256": "c9b7e970f00e84a0a488201d5ffee4678f36046eff500b11a5b25a2a4ec6589f" + "sha256": "7ed5f58369ff2f4d870045caeec9cf4dcb398956af324bf86c5925ce578bba16", + "sourceSha256": "c9b7e970f00e84a0a488201d5ffee4678f36046eff500b11a5b25a2a4ec6589f" }, { "path": "firefly-light.svg", - "sha256": "e365eff656bca5807f5bf722db0f3c7de5b72120ac158d043013df7f0c96fca2" + "sha256": "2789f482d8a456f744e3dd0034ed9613b3606fe4badabcd09e70d7e916b6844e", + "sourceSha256": "e365eff656bca5807f5bf722db0f3c7de5b72120ac158d043013df7f0c96fca2" } - ] + ], + "transportNormalization": "Replace trailing LF bytes with exactly one LF; preserve all other bytes." } diff --git a/assets/tools/brand-source/banner-dark.svg b/assets/tools/brand-source/banner-dark.svg index a2558904..fecfbbf6 100644 --- a/assets/tools/brand-source/banner-dark.svg +++ b/assets/tools/brand-source/banner-dark.svg @@ -1 +1 @@ -agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file +agentic by Firefly — intelligence, composedagentic by Firefly diff --git a/assets/tools/brand-source/banner-light.svg b/assets/tools/brand-source/banner-light.svg index db465f77..76585c12 100644 --- a/assets/tools/brand-source/banner-light.svg +++ b/assets/tools/brand-source/banner-light.svg @@ -1 +1 @@ -agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file +agentic by Firefly — intelligence, composedagentic by Firefly diff --git a/assets/tools/brand-source/firefly-light.svg b/assets/tools/brand-source/firefly-light.svg index c175598a..2355eaa1 100644 --- a/assets/tools/brand-source/firefly-light.svg +++ b/assets/tools/brand-source/firefly-light.svg @@ -1 +1 @@ -Firefly \ No newline at end of file +Firefly diff --git a/assets/tools/brand-source/logo-dark-mono.svg b/assets/tools/brand-source/logo-dark-mono.svg index 50adc362..ff711dba 100644 --- a/assets/tools/brand-source/logo-dark-mono.svg +++ b/assets/tools/brand-source/logo-dark-mono.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/assets/tools/brand-source/logo-dark.svg b/assets/tools/brand-source/logo-dark.svg index 76b129ec..2e38e008 100644 --- a/assets/tools/brand-source/logo-dark.svg +++ b/assets/tools/brand-source/logo-dark.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/assets/tools/brand-source/logo-light-mono.svg b/assets/tools/brand-source/logo-light-mono.svg index 59e9ac2b..887711d6 100644 --- a/assets/tools/brand-source/logo-light-mono.svg +++ b/assets/tools/brand-source/logo-light-mono.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/assets/tools/brand-source/logo-light.svg b/assets/tools/brand-source/logo-light.svg index e22f3bb6..d8bb60f9 100644 --- a/assets/tools/brand-source/logo-light.svg +++ b/assets/tools/brand-source/logo-light.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/assets/tools/build_brand_assets.py b/assets/tools/build_brand_assets.py index 86b886a4..643b6b8d 100644 --- a/assets/tools/build_brand_assets.py +++ b/assets/tools/build_brand_assets.py @@ -273,7 +273,7 @@ def esc(s): def write_svg(name, svg): - OUTPUTS[name] = svg + OUTPUTS[name] = svg.rstrip("\n") + "\n" # --------------------------------------------------------------------------- kit diff --git a/docs/assets/banner-light.svg b/docs/assets/banner-light.svg index db465f77..76585c12 100644 --- a/docs/assets/banner-light.svg +++ b/docs/assets/banner-light.svg @@ -1 +1 @@ -agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file +agentic by Firefly — intelligence, composedagentic by Firefly diff --git a/docs/assets/banner.svg b/docs/assets/banner.svg index a2558904..fecfbbf6 100644 --- a/docs/assets/banner.svg +++ b/docs/assets/banner.svg @@ -1 +1 @@ -agentic by Firefly — intelligence, composedagentic by Firefly \ No newline at end of file +agentic by Firefly — intelligence, composedagentic by Firefly diff --git a/docs/assets/brand-logo-light.svg b/docs/assets/brand-logo-light.svg index e22f3bb6..d8bb60f9 100644 --- a/docs/assets/brand-logo-light.svg +++ b/docs/assets/brand-logo-light.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/docs/assets/brand-logo.svg b/docs/assets/brand-logo.svg index 76b129ec..2e38e008 100644 --- a/docs/assets/brand-logo.svg +++ b/docs/assets/brand-logo.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly diff --git a/docs/assets/logo.svg b/docs/assets/logo.svg index 76b129ec..2e38e008 100644 --- a/docs/assets/logo.svg +++ b/docs/assets/logo.svg @@ -1 +1 @@ -agentic by Firefly \ No newline at end of file +agentic by Firefly