Skip to main content

FinanFut Intelligence Python SDK

SDK oficial de FinanFut Intelligence per integrar agents, intents, memòria i fluxos d'orquestració des de Python.

Índex


Instal·lació

pip install finanfut-sdk

Requisit: Python >= 3.12.


Configuració

Pots inicialitzar el client amb paràmetres directes o bé mitjançant fitxer de configuració + variables d'entorn.

Fitxer local (~/.finanfut/config.json)

mkdir -p ~/.finanfut
{
  "api_key": "YOUR_API_KEY",
  "application_id": "YOUR_APPLICATION_ID",
  "api_url": "https://api.intelligence.finanfut.com"
}

Variables d'entorn suportades

  • FINANFUT_API_KEY
  • FINANFUT_APPLICATION_ID
  • FINANFUT_API_URL

FINANFUT_API_URL accepta host base o URL amb /api o /api/v1; l'SDK la normalitza per evitar segments duplicats.


Quickstart

from finanfut_sdk import FinanFutClient

client = FinanFutClient(
    api_key="YOUR_API_KEY",
    application_id="YOUR_APPLICATION_ID",
)

response = client.interact.query(
    query="Hola! Programa una reunió demà a les 10.",
    application_agent_id="YOUR_APPLICATION_AGENT_ID",
    intent_id="YOUR_INTENT_ID",
)

print(response.answer)
print(response.model, response.ai_model_id)

Capacitats del client

FinanFutClient exposa aquests mòduls:

  • client.interact
  • client.agents
  • client.intents
  • client.applications
  • client.application_agents
  • client.memory
  • client.knowledge
  • client.documents
  • client.data_import
  • client.ocr
  • client.models
  • client.contexts
  • client.context_sessions
  • client.billing
  • client.analytics
  • client.access_tokens

També pots activar mode sandbox amb FinanFutClient.for_sandbox(...) o dry_run=True.


Interact API (/api/v1/public/requests)

client.interact.query(...) requereix:

  • query
  • intent_id
  • una referència d'agent: application_agent_id o agent_slug o agent_id

Paràmetres opcionals rellevants:

  • intent: etiqueta textual de l'intent (p. ex. knowledge.answer) per mantenir traçabilitat humana al lifecycle del request.
  • parameters: claus addicionals per a routing/execució (incloent compatibilitat amb intent_name).
  • parameters.knowledge_source: controla on cerca el runtime per intents de coneixement. auto és el valor per defecte: usa el knowledge graph de l'aplicació quan no s'envia cap document/context, amb fallback a knowledge_records, i usa chunks quan s'envia document_id o context_id. També accepta application, graph, application_graph, document, context i mixed.
  • knowledge_source, knowledge_record_type, max_knowledge_records i knowledge_min_score: dreceres tipades de client.interact.query(...) per no haver de construir manualment parameters.
  • mode, execution_mode, dry_run, metadata i extras s'accepten per compatibilitat amb wrappers existents. Els controls no suportats com a arguments top-level pel backend es pleguen dins el payload públic; dry_run es propaga com a parameters.dry_run.

Exemple amb context i document:

response = client.interact.query(
    query="Respon segons aquest context",
    intent_id="INTENT_UUID",
    intent="knowledge.answer",
    application_agent_id="APP_AGENT_UUID",
    context_id="CONTEXT_UUID",
    document_id="DOCUMENT_UUID",
    parameters={"lang": "ca"},
)

print(response.answer)
print(response.tokens)

Exemple amb knowledge d'aplicació per defecte:

response = client.interact.query(
    query="Com es crea un torneig?",
    intent_id="INTENT_UUID",
    intent="knowledge.answer",
    application_agent_id="APP_AGENT_UUID",
)

Exemple combinant knowledge d'aplicació i chunks documentals:

response = client.interact.query(
    query="Com es crea un torneig segons el contracte carregat?",
    intent_id="INTENT_UUID",
    intent="knowledge.answer",
    application_agent_id="APP_AGENT_UUID",
    document_id="DOCUMENT_UUID",
    parameters={"knowledge_source": "mixed"},
)

Streaming incremental via SDK:

for chunk in client.interact.stream(
    query="Resposta curta: com es crea un torneig?",
    intent="knowledge.answer",
    application_agent_id="APP_AGENT_UUID",
    parameters={"response_length": "short"},
    timeout=60.0,
):
    if chunk.get("delta"):
        print(chunk["delta"], end="", flush=True)

    if chunk["event"] in {"request.completed", "response.completed"}:
        print("\nStream completat")

    if chunk.get("response"):
        print("\nResposta final:", chunk["response"].answer)

Patró de baix nivell, útil si el client vol reprendre amb after_sequence:

request_id = client.interact.query_async(
    query="Escriu un resum executiu",
    intent="knowledge.answer",
    application_agent_id="APP_AGENT_UUID",
    stream=True,
)

last_sequence = 0
for event in client.requests.stream_events(request_id, after_sequence=last_sequence):
    data = event["data"]
    if data.get("sequence_no"):
        last_sequence = int(data["sequence_no"])

    payload = data.get("payload") or {}
    if payload.get("delta"):
        print(payload["delta"], end="", flush=True)
    if event["event"] in {"request.completed", "response.completed"}:
        break

final_response = client.requests.wait(request_id)

En consultes curtes sense context_id, document_id, document_ids, session_id ni configuració de memòria explícita, parameters={"response_length": "short"} permet al backend aplicar la política de baixa latència i saltar la recuperació de memòria.

Quan el backend retorna una resposta estructurada dins envelope.user_output.structured_json, l'SDK la promou automàticament com a response.answer i també la deixa disponible a:

  • response.structured_answer
  • response.envelope.user_output.structured_json

Exemple per a content.generate:

response = client.interact.query(
    query="Prepara una publicació de 100 paraules sobre la jornada",
    intent_id="INTENT_UUID",
    application_agent_id="APP_AGENT_UUID",
)

if isinstance(response.answer, dict):
    print(response.answer["post_text"])
    print(response.answer.get("image_url"))
    print(response.answer.get("freshness_status"))

Recuperació de l’acceptació del briefing (1.3.12)

client.requests.lookup(idempotency_key=..., session_id=..., application_agent_id=..., intent_id=..., timeout=10) fa un GET exacte a /api/v1/public/requests/lookup sota client.execution_scope(...) i retorna únicament data.request_id. L’aplicació S2S ha de reconstruir permisos actuals; no utilitzis context aportat pel model. No envia feina, no cerca per prompt i un 404 no prova absència ni autoritza reenviar. Desa l’ID abans de recollir el resultat amb els mètodes existents. Vegeu contracte operatiu. La versió 1.3.12 està preparada localment; publicació i desplegament pendents.

Aplicacions i manifest SDK

apps = client.applications.list()
app = client.applications.get("APP_UUID")

manifest = client.applications.get_manifest("APP_UUID")
if manifest:
    print(manifest.manifest_version)

bootstrap = client.applications.bootstrap_manifest("APP_UUID")
if bootstrap:
    print(bootstrap.agents_by_id.keys())

Pots fer peticions condicionals amb ETag via if_none_match; si el backend respon 304, el client retorna None.


Catàleg de models i model-settings

catalog = client.models.list(category="chat", only_active=True)

settings = client.models.list_application_settings(
    application_id=client.application_id,
    category="chat",
)

updated = client.models.update_application_setting(
    application_id=client.application_id,
    agent_ref="default",
    payload={
        "ai_model_id": catalog[0].id,
        "category": "chat",
        "temperature": 0.2,
    },
)

print(updated.ai_model_id)

Knowledge incremental

client.knowledge permet enviar canvis de coneixement sense pujar documents complets cada vegada. El backend desa events pendents i sync() els consolida en records versionats per alimentar cerca, FAQ i agents documentals.

event = client.knowledge.record(
    event_type="backend.endpoint.updated",
    record_key="sports.tournaments.create",
    record_type="backend.endpoint",
    title="Creació de tornejos",
    content="POST /tournaments crea un torneig i accepta registration_deadline.",
    metadata={"domain": "sports", "module": "tournaments"},
)

sync = client.knowledge.sync(async_=True)
results = client.knowledge.search(
    "Com creo un torneig?",
    filters={"domain": "sports"},
    min_score=0.1,
)
print(event.id, sync.updated_records, results.results[0].record.title)

Discovery i Knowledge Graph:

discovery = client.knowledge.discover(
    frontend_routes=[
        {
            "path": "/config/tournaments",
            "component": "TournamentConfig",
            "api_paths": [{"method": "POST", "path": "/api/v1/tournaments"}],
        }
    ],
    sync_records=True,
)

graph = client.knowledge.graph(relation_type="USES_CONNECTOR")
print(discovery.nodes, len(graph.edges))

Documents i document QA

client.documents.upload(...) admet file_path, content o text.

from pathlib import Path

# Fitxer físic
pdf_doc = client.documents.upload(
    file_path=Path("knowledge.pdf"),
    document_type="context_general",
)

# Text lliure
schema_doc = client.documents.upload(
    text='{"name": "Ada", "role": "engineer"}',
    file_name="profile.json",
    mime_type="application/json",
    document_type="schema_contract",
)

print(pdf_doc.document_type, schema_doc.document_type_version)

Altres operacions habituals:

items = client.documents.list(limit=20)
detail = client.documents.get(str(pdf_doc.id))
answer = client.documents.ask(str(pdf_doc.id), "Resumeix els punts clau")

Upload asíncron amb polling:

accepted = client.documents.upload(
    text="# FAQ async",
    file_name="faq.md",
    mime_type="text/markdown",
    async_mode=True,
)

if hasattr(accepted, "job_id"):
    while True:
        job = client.documents.get_upload_job(str(accepted.job_id))
        if job.status == "completed":
            print("Document llest:", job.document.id if job.document else accepted.document_id)
            break
        if job.status == "failed":
            raise RuntimeError(job.error or "job_failed")

Contexts i context sessions

Contexts persistents

ctx = client.contexts.create(
    name="Context operatiu",
    description="Documents base per al flux",
    documents=[str(pdf_doc.id)],
)

ctx = client.contexts.add_documents(ctx.id, [str(schema_doc.id)])
print(ctx.id, len(ctx.documents))

Sessions de context

session = client.context_sessions.create(
    name="Sessió de proves",
    context_id=ctx.id,
)

client.context_sessions.add_message(
    session.id,
    agent_name="sports_operations_agent",
    query="Quina és la següent acció recomanada?",
    answer="Revisar el calendari i validar la disponibilitat.",
)

OCR mapping

client.ocr.map(...) crida POST /api/v1/ocr/mappings i transforma una imatge, un PDF amb text extractable, un fitxer de text o un document ja persistit en un JSON alineat amb el contracte que li passes.

Exemple amb una imatge local:

from finanfut_sdk import FinanFutClient

client = FinanFutClient()

contract = {
    "type": "object",
    "additionalProperties": False,
    "required": ["competition", "home_team", "away_team", "score"],
    "properties": {
        "competition": {"type": ["string", "null"]},
        "home_team": {"type": ["string", "null"]},
        "away_team": {"type": ["string", "null"]},
        "score": {
            "type": "object",
            "additionalProperties": False,
            "required": ["home", "away"],
            "properties": {
                "home": {"type": ["integer", "null"]},
                "away": {"type": ["integer", "null"]},
            },
        },
    },
}

result = client.ocr.map(
    file_path="acta.jpg",
    profile_key="sports.match_report",
    output_contract=contract,
    instructions="Extreu només dades visibles a l'acta. No inventis valors.",
    confidence_threshold=0.78,
)

print(result.answer.mapped_json)
print(result.answer.validation.status)
print(result.answer.extraction.confidence)

Fonts acceptades:

  • file_path: camí local; l'SDK llegeix el fitxer i l'envia en base64.
  • content: bytes ja carregats en memòria.
  • content_base64: contingut base64 o data URL ja preparat.
  • document_id: reutilitza un document existent de la mateixa aplicació.

Opcions útils:

  • profile_key: generic.document_mapping o sports.match_report.
  • include_raw_text_excerpt: demana un extracte textual quan és operativament necessari.
  • persist_source: desa la font com a document intern i retorna document_id.
  • timeout: timeout HTTP per a documents grans o models més lents.

La resposta tipada és OCRMappingResponse. El resultat útil viu a result.answer.mapped_json; valida result.answer.validation.status == "valid" abans d'automatitzar accions. Si rep "needs_review", revisa missing_fields, errors, warnings i field_evidence.

Els PDFs escanejats no s'han d'enviar com a PDF en v1. Cal convertir la pàgina a imatge i enviar-la amb file_path, content o content_base64.


Data import (CSV/PDF → JSON)

preview = client.data_import.upload_transient_csv(file_path="ingesta.csv")

result = client.data_import.transform_data(
    application_id=client.application_id,
    intent_id="UUID_INTENT_TRANSFORM_DATA",
    transient_csv=preview,
    contract_document_id="UUID_DATA_IMPORT_CONTRACT",
)

print(result.items[0] if result.items else result.response)

Per PDF:

preview = client.data_import.upload_transient_pdf(file_path="factura.pdf")
result = client.data_import.transform_document(
    application_id=client.application_id,
    intent_id="UUID_INTENT_TRANSFORM_DOCUMENT",
    transient_document=preview,
    contract_document_id="UUID_DATA_IMPORT_CONTRACT",
)

Billing, analytics i access tokens

usage = client.billing.get_usage(period="month")
print(usage.tokens_used, usage.cost)

logs = client.analytics.logs()
requests_trace = client.analytics.requests()
print(len(logs), len(requests_trace))

tokens = client.access_tokens.list()
print(len(tokens.items))

Gestió d'errors

L'SDK eleva excepcions tipades (ValidationError, AuthenticationError, RateLimitError, etc.) segons l'estat HTTP i el payload del backend.

Per errors de contracte (UNPROCESSABLE_OUTPUT_CONTRACT) retornats com {"error": "<text>"}, el missatge complet es propaga en una ValidationError perquè no es perdi el detall del contracte fallit.


CLI

finanfut init
finanfut interact "Hola" --agent-id "APP_AGENT_UUID" --intent-id "INTENT_UUID"
finanfut usage --period month
finanfut agents list

Flags globals disponibles: --api-key, --application-id, --api-url, --config, --dry-run.


Llicència

Aquest projecte es distribueix sota llicència MIT.

Context de subjecte per a recursos vinculats (1.3.11)

El backend S2S construeix server_scope després de verificar l’usuari/perfil i els permisos actuals. No l’obtinguis del navegador o del model. El receptor exigeix API key amb contexts:interact (sessions també contexts:sessions), camps d’ExecutionScope, issued_at/expires_at amb zona i vigència màxima de 600 s.

with client.execution_scope(server_scope):
    status = client.requests.get(request_id)
    result = client.requests.wait(request_id)

El mateix bloc cobreix sessions i stream; consumeix els iteradors dins del bloc. ContextVar evita mutacions compartides de headers i restaura el context en finally. No és autenticació d’usuari ni signatura addicional; el servidor atesta el scope amb la clau d’aplicació. No es renova automàticament la vigència en polling. Sense scope no es poden llegir recursos vinculats; amb scope no s’adopten legacy. 1.3.11 és una preparació local pendent de publicació i rollout coordinat amb el receptor. Contracte operatiu.

Release

See independent SDK release workflows. Python tags use python-sdk-v*; TypeScript tags use typescript-sdk-v*. Generic v* tags no longer publish either package.

Metadata

Release files for finanfut-sdk 1.3.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for finanfut-sdk 1.3.12
File Size Uploaded Provenance
finanfut_sdk-1.3.12.tar.gz 51.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for finanfut-sdk 1.3.12
File Interpreter ABI Platform
finanfut_sdk-1.3.12-py3-none-any.whl Python 3 none any Details

Total release size: 102.6 kB

Release files / finanfut_sdk-1.3.12.tar.gz

Download URL finanfut_sdk-1.3.12.tar.gz
Size 51.0 kB
Tags Source
SHA-256 checksum
How to use checksums
074596874b0d11a7f0619ee39aea33386787a7f5a18087646e0ca8c4eb204cd0
BLAKE2b-256 checksum
How to use checksums
780919481956770bb7550395e0d209b9142344539971aa70ff5cd3c5264d2ac8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / finanfut_sdk-1.3.12-py3-none-any.whl

Download URL finanfut_sdk-1.3.12-py3-none-any.whl
Size 51.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
172b0458ba46c83191065e703a520541136316f285786aeeac73afb97f7d0797
BLAKE2b-256 checksum
How to use checksums
c8b73472baa15afdd6cd1a413af8bb892a303dd432d401bd27bdf7bef860f56a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for finanfut-sdk 1.3.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page