Het bouwen van een multi-agentsysteem met CrewAI wordt interessanter wanneer verschillende agents verschillende modellen kunnen gebruiken.
Een onderzoeker kan baat hebben bij een snel en voordelig model, een analist kan een sterker redeneermodel nodig hebben, en een schrijver kan een model nodig hebben dat is geoptimaliseerd voor hoogwaardige longform-generatie. Traditioneel betekent het verbinden van deze agents met verschillende providers het beheren van aparte API-referenties, endpoints, SDK’s, factureringssystemen en providerspecifieke configuratie.
Een schonere architectuur is om CrewAI de agents en workflow te laten beheren terwijl CometAPI de modeltoegang beheert.
CometAPI biedt een OpenAI-compatibel endpoint op https://api.cometapi.com/v1, zodat applicaties aanvragen naar modellen van meerdere providers via één gemeenschappelijke API-interface kunnen routeren. De huidige quickstart-documentatie ondersteunt ook het gebruik van de standaard OpenAI Python SDK door de API-sleutel en base URL te wijzigen.
In deze tutorial bouw je een CrewAI-workflow met drie agents met:
- Gemini 3.7 Flash voor research
- Claude Opus 5 voor analyse
- GPT-5.6 voor het uiteindelijke schrijven
- Eén CometAPI API-sleutel
- Eén API base URL
- Per-agent modelconfiguratie
- Begrensde fallback voor tijdelijke storingen
- CrewAI-checkpointing voor herstel in productie
- Tracking van token- en uitvoeringsgebruik
- Server-side modelvalidatie
De belangrijke architecturale scheidslijn is eenvoudig:
CrewAI regelt de agent-orchestratie. CometAPI regelt de modeltoegang. Model-ID’s bepalen de routing.
Wat is CrewAI Multi-Agent Model Routing?
CrewAI is een Python-framework voor het creëren van agents, taken, crews en multi-agent-workflows. Elke agent kan zijn eigen LLM-configuratie hebben, terwijl de Crew coördineert hoe die agents taken uitvoeren en context uitwisselen.
De huidige LLM-configuratie van CrewAI ondersteunt expliciete model-, api_key- en base_url-instellingen, inclusief aangepaste OpenAI-compatibele endpoints.
Dat maakt een multi-modelarchitectuur eenvoudig:
CometAPI │ https://api.cometapi.com/v1 │ ┌───────────────────┼───────────────────┐ │ │ │ Researcher Analyst Writer │ │ │ Gemini 3.7 Flash Claude Opus 5 GPT-5.6
De agents blijven logisch gescheiden, maar hun modeltoegang is gecentraliseerd.
Dat is iets anders dan zeggen dat alle modellen inwisselbaar zijn. Een OpenAI-compatibele API biedt een gemeenschappelijke aanvraaginterface; het garandeert niet identieke contextlimieten, toolondersteuning, bedieningsopties voor redeneren, outputgedrag, latentie of prijsstelling.
Dat onderscheid is belangrijk bij het ontwerpen van routing voor productie.
Waarom CometAPI gebruiken met CrewAI?
Het belangrijkste voordeel is niet dat CrewAI plotseling een multi-provider framework wordt. CrewAI ondersteunt al meerdere LLM-providers.
Het voordeel is dat de modeltoegang kan worden geconsolideerd achter één API-laag.
Zonder een uniforme API-laag kan een workflow met drie agents er zo uitzien:
| Agent | Provider | Inloggegevens | Integratie |
|---|---|---|---|
| Researcher | Google API-sleutel | Providerspecifiek | |
| Analyst | Anthropic | Anthropic API-key | Providerspecifiek |
| Writer | OpenAI | OpenAI API-key | Providerspecifiek |
Met CometAPI:
| Agent | Model | Inloggegevens | Endpoint |
|---|---|---|---|
| Researcher | Gemini 3.7 Flash | CometAPI-key | CometAPI |
| Analyst | Claude Opus 5 | CometAPI-key | CometAPI |
| Writer | GPT-5.6 | CometAPI-key | CometAPI |
De huidige quickstart-documentatie van CometAPI beschrijft het endpoint als een drop-in vervanging voor de OpenAI API base URL en biedt modellen van meerdere providers via dezelfde service.
Dit geeft de applicatie een nuttige scheiding:
CrewAI
- Definieert agentrollen
- Definieert taken
- Geeft context door
- Stuurt de uitvoering aan
- Beheert agent-iteraties
- Verzorgt crew-niveau orchestratie
CometAPI
- Levert een gemeenschappelijke modeltoegangslaag
- Centraliseert API-authenticatie
- Biedt modelrouting via model-ID’s
- Geeft de applicatie één API-endpoint
- Verleent gecentraliseerd inzicht in gebruik en facturatie
Wat bouwt deze CrewAI-workflow?
Het voorbeeld maakt drie sequentiële agents.
| CrewAI-agent | Primair model | Fallback | Rol |
|---|---|---|---|
| Market Researcher | gemini-3.7-flash | gpt-5.6 | Feiten verzamelen en research |
| Product Analyst | claude-opus-5 | gpt-5.6 | Bewijs synthetiseren en trade-offs |
| Technical Writer | gpt-5.6 | gemini-3.7-flash | Het definitieve beslismemo produceren |
Dit is een voorbeeld van een routingbeleid, geen benchmarkranglijst.
Het juiste model voor je agent hangt af van:
- taakcomplexiteit
- vereiste contextlengte
- toolgebruik
- vereisten voor gestructureerde output
- latentie
- betrouwbaarheid
- tokenkosten
- outputkwaliteit
- applicatiespecifieke evaluatieresultaten
Een nuttige regel is:
Kies een model voor het werk dat de agent doet, niet simpelweg voor de provider waar het vandaan komt.
Welk model moet elke CrewAI-agent gebruiken?
Voor dit voorbeeld volgt de modeltoewijzing een eenvoudige strategie van kosten versus mogelijkheden.
Researcher: Gemini 3.7 Flash
Research omvat vaak het verwerken van relatief veel informatie en het produceren van een compact tussenresultaat.
Een snel model kan daarom nuttig zijn voor onderzoekstaken met hoog volume.
"researcher": "gemini-3.7-flash"
Analyst: Claude Opus 5
De analist heeft een smallere maar meer redeneersintensieve rol. Hij/zij ontvangt de researchoutput en zet die om in een aanbeveling.
"analyst": "claude-opus-5"
Writer: GPT-5.6
De laatste agent zet de research en analyse om in een ontwikkelaarsgericht beslismemo.
"writer": "gpt-5.6"
Het belangrijkste is niet deze exacte drie toewijzingen. Je applicatie moet kandidaatmodellen evalueren op representatieve taken voordat je het routingbeleid vastlegt.
Wat heb je nodig voordat je start?
Je hebt nodig:
- Python 3.10+
- CrewAI
- OpenAI Python SDK-compatibiliteit
python-dotenv- Een CometAPI API-sleutel
- De model-ID’s die je wilt gebruiken
De huidige Python-integratie van CometAPI ondersteunt de OpenAI-compatibele API, en het officiële CometAPI Python-pakket documenteert COMETAPI_KEY en COMETAPI_BASE_URL als op omgevingsvariabelen gebaseerde configuratieopties.
Het standaardendpoint is:
https://api.cometapi.com/v1
Controleer vóór deployment of je geselecteerde model-ID’s momenteel beschikbaar zijn en het endpoint en de parameters ondersteunen die jouw CrewAI-werkload vereist. Modelcatalogi en prijzen kunnen veranderen.
Hoe installeer je CrewAI en de afhankelijkheden?
Maak een nieuwe Python-omgeving:
python -m venv .venv
Activeer deze:
source .venv/bin/activate
Op Windows:
.venv\Scripts\Activate.ps1
Installeer vervolgens de dependencies:
pip install "crewai[openai]" openai python-dotenv
Het expliciet gebruiken van openai is bewust, omdat de fallback-implementatie hieronder OpenAI SDK-exceptieklassen direct importeert.
Voor productie: pin de versies die je test in plaats van onbeperkt op de nieuwste versies te vertrouwen.
Bijvoorbeeld:
crewai==YOUR_TESTED_VERSIONopenai==YOUR_TESTED_VERSIONpython-dotenv==YOUR_TESTED_VERSION
De LLM-laag van CrewAI is actief in ontwikkeling, dus controleer de exacte constructor en providerconfiguratie tegen de CrewAI-versie die je applicatie gebruikt. De huidige documentatie van CrewAI ondersteunt het configureren van een LLM met een aangepaste base_url en API-sleutel.
Hoe configureer je de CometAPI API-sleutel?
Maak een .env-bestand:
COMETAPI_KEY=your_cometapi_keyCOMETAPI_BASE_URL=https://api.cometapi.com/v1
Laad deze waarden in Python:
import osfrom dotenv import load_dotenvload_dotenv()COMETAPI_KEY = os.environ["COMETAPI_KEY"]COMETAPI_BASE_URL = os.getenv( "COMETAPI_BASE_URL", "https://api.cometapi.com/v1",)
Commit .env nooit naar Git.
Voeg het toe aan .gitignore:
.env.venv/__pycache__/
De API-sleutel moet een server-side referentie blijven. De huidige quickstart-richtlijnen van CometAPI bevelen eveneens aan om de sleutel in omgevingsvariabelen op te slaan in plaats van in broncode.
Hoe verbind je CrewAI met CometAPI?
Het LLM-object van CrewAI kan een modelnaam, API-sleutel en aangepaste base URL ontvangen.
Maak een helper:
from crewai import LLMdef cometapi_llm(model_id: str) -> LLM: return LLM( model=model_id, base_url=COMETAPI_BASE_URL, api_key=COMETAPI_KEY, timeout=60.0, max_retries=0, )
Dit verdient de voorkeur boven het afzonderlijk inbedden van dezelfde configuratie in elke agent.
Elke agent heeft nu alleen een model-ID nodig:
research_llm = cometapi_llm("gemini-3.7-flash")analysis_llm = cometapi_llm("claude-opus-5")writing_llm = cometapi_llm("gpt-5.6")
Waarom max_retries=0 instellen?
De reden is fallback-controle.
Als de onderliggende LLM-client automatisch retries uitvoert en je applicatie ook fallback implementeert, kan één fout meerdere verborgen verzoeken worden voordat de fallback-logica wordt uitgevoerd.
Voor een tutorial met expliciete routing is het schoner om de applicatie te laten beslissen wanneer opnieuw te proberen of van model te wisselen.
Hoe definieer je het modelroutingbeleid?
Houd routing buiten je prompts:
PRIMARY_MODELS = { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6",}FALLBACK_MODELS = { "researcher": "gpt-5.6", "analyst": "gpt-5.6", "writer": "gemini-3.7-flash",}
Dit creëert een duidelijke configuratiegrens.
Je kunt dezelfde mapping later verplaatsen naar:
- omgevingsconfiguratie
- YAML
- JSON
- een database
- feature flags
- een interne model-routingservice
zonder de agentprompts te herschrijven.
Hoe bouw je de drie CrewAI-agents?
Maak één LLM-object per agent.
from crewai import Agentdef build_agents(model_map: dict[str, str]): researcher = Agent( role="Market Researcher", goal="Collect the facts needed to answer the topic", backstory=( "You create concise, source-aware research briefs " "and clearly separate facts from assumptions." ), llm=cometapi_llm(model_map["researcher"]), max_iter=3, allow_delegation=False, ) analyst = Agent( role="Product Analyst", goal="Turn research into a defensible recommendation", backstory=( "You identify evidence, assumptions, risks, " "and trade-offs before making recommendations." ), llm=cometapi_llm(model_map["analyst"]), max_iter=3, allow_delegation=False, ) writer = Agent( role="Technical Writer", goal="Produce a concise technical decision memo", backstory=( "You write clear technical explanations " "without unnecessary marketing language." ), llm=cometapi_llm(model_map["writer"]), max_iter=3, allow_delegation=False, ) return researcher, analyst, writer
De modeltoewijzing is nu volledig onafhankelijk van de roldefinitie van de agent.
Dat is wat modelrouting praktisch maakt.
Hoe verbind je de agents met sequentiële taken?
Maak drie taken:
from crewai import Taskdef build_tasks(researcher, analyst, writer): research_task = Task( description=( "Research this topic: {topic}. " "Return the key facts, uncertainties, " "and relevant sources that the analyst should consider." ), expected_output=( "A compact research brief containing facts, " "uncertainties, and source references." ), agent=researcher, ) analysis_task = Task( description=( "Using the research brief, analyze {topic}. " "Identify the strongest conclusion and explain " "the major trade-offs." ), expected_output=( "A decision outline with evidence, " "assumptions, risks, and trade-offs." ), agent=analyst, context=[research_task], ) writing_task = Task( description=( "Write a concise technical decision memo about {topic}. " "State the recommendation early and preserve " "important caveats." ), expected_output="A polished technical decision memo in Markdown.", agent=writer, context=[research_task, analysis_task], ) return research_task, analysis_task, writing_task
De afhankelijkheidsketen is:
Topic ↓Research ↓Analysis ↓Final memo
De analist ontvangt de output van de researchtaak, terwijl de schrijver zowel de research- als de analysecontext krijgt.
Hoe bouw je de Crew?
Combineer de agents en taken:
from crewai import Crew, Processdef build_crew(model_map: dict[str, str]) -> Crew: researcher, analyst, writer = build_agents(model_map) research_task, analysis_task, writing_task = build_tasks( researcher, analyst, writer, ) return Crew( agents=[researcher, analyst, writer], tasks=[ research_task, analysis_task, writing_task, ], process=Process.sequential, verbose=True, )
Nu is de modelrouting volledig configuratiegestuurd.
Het wijzigen van:
"researcher": "gemini-3.7-flash"
naar een ander ondersteund model vereist geen wijziging in de researchprompt of taakdefinitie.
Hoe moet fallback voor CrewAI-modellen werken?
Hier is een productiegerichte implementatie zorgvuldiger.
Een veelgemaakte fout is:
Elke fout ↓Model wisselen
Dat is te agressief.
Bijvoorbeeld, deze fouten zouden over het algemeen geen fallback moeten activeren:
400 Bad Request401 Unauthorized403 Forbidden404 Not Found422 Validation Error
Van model wisselen lost geen ongeldige API-sleutel of ongeldige aanvraag op.
Fallback is passender voor tijdelijke storingen zoals:
408 Request Timeout429 Rate Limit500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway TimeoutConnection errorTimeout
Het fallbackbeleid zou daarom moeten zijn:
Alleen opnieuw proberen of van model wisselen bij begrensde, tijdelijke storingen en alleen wanneer het fallbackmodel hetzelfde aanvraagcontract ondersteunt.
Hoe detecteer je retrybare fouten?
Je kunt de foutklassen van de OpenAI SDK gebruiken:
from collections.abc import Iteratorfrom openai import ( APIConnectionError, APIStatusError, APITimeoutError,)def exception_chain(error: BaseException) -> Iterator[BaseException]: current: BaseException | None = error seen: set[int] = set() while current is not None and id(current) not in seen: seen.add(id(current)) yield current current = ( current.__cause__ or current.__context__ )def should_fallback(error: BaseException) -> bool: for current in exception_chain(error): if isinstance( current, (APIConnectionError, APITimeoutError), ): return True if isinstance(current, APIStatusError): return ( current.status_code in {408, 429} or current.status_code >= 500 ) return False
Dit sluit bewust configuratiefouten met 400-status uit, behalve 408 en 429.
Moet je de hele crew opnieuw proberen of alleen de mislukte agent?
Er zijn twee verschillende fallbackstrategieën.
Fallback op crew-niveau
De simpelste implementatie is:
Crew starten ↓fout ↓routing wijzigen ↓crew opnieuw uitvoeren
Dit is gemakkelijk te begrijpen, maar kan voltooide taken herhalen.
Bijvoorbeeld:
Research → voltooidAnalysis → voltooidWriter → mislukt
Een volledige kickoff()-retry kan uitvoeren:
Research → opnieuwAnalysis → opnieuwWriter → fallback
Dat verhoogt:
- tokenverbruik
- latentie
- API-kosten
- potentiële neveneffecten
Herstel op taakniveau
Een productieworkflow zou in plaats daarvan voltooide werkzaamheden moeten checkpointen:
Research ↓checkpoint ↓Analysis ↓checkpoint ↓Writer faalt ↓retry writer met fallback
CrewAI biedt momenteel checkpointing die de executiestaat opslaat en toestaat een run te hervatten na een fout. Het gedocumenteerde checkpointgedrag slaat voltooide taken over en gaat verder stroomafwaarts vanaf de opgeslagen toestand.
Dit is de betere architectuur voor dure of neveneffect-producerende workflows.
Hoe voeg je CrewAI-checkpointing toe?
Schakel voor productieworkflows checkpointing in op de crew:
crew = Crew( agents=[researcher, analyst, writer], tasks=[ research_task, analysis_task, writing_task, ], process=Process.sequential, checkpoint=True, verbose=True,)
Het checkpointingsysteem van CrewAI kan de uitvoeringsstaat na taakvoltooiing persistent opslaan en de crew herstellen vanaf een checkpoint.
Een herstelde run kan bijvoorbeeld gebruiken:
from crewai import CheckpointConfigresult = crew.kickoff( from_checkpoint=CheckpointConfig( restore_from="./.checkpoints/checkpoint.json", ))
De exacte checkpointconfiguratie moet overeenkomen met de CrewAI-versie die door je project wordt gebruikt.
Het belangrijkste architecturale punt is:
Eerst checkpointen, daarna fallback.
Dit voorkomt dat een tijdelijke modelfout dure, voltooide werkzaamheden opnieuw laat draaien.
Hoe implementeer je een eenvoudige begrensde fallback?
Voor een tutorial kun je nog steeds een eenvoudige fallback op crew-niveau demonstreren.
def run_with_fallback(topic: str): routes = [ PRIMARY_MODELS, { **PRIMARY_MODELS, "writer": FALLBACK_MODELS["writer"], }, { **PRIMARY_MODELS, "analyst": FALLBACK_MODELS["analyst"], "writer": FALLBACK_MODELS["writer"], }, ] last_error = None for attempt, model_map in enumerate(routes, start=1): try: crew = build_crew(model_map) result = crew.kickoff( inputs={"topic": topic} ) return result, model_map except Exception as error: last_error = error if not should_fallback(error): raise if attempt == len(routes): raise print( f"Transient failure on attempt {attempt}. " f"Trying bounded fallback route.", flush=True, ) raise RuntimeError( "Crew execution failed after all fallback routes." ) from last_error
Let op het belangrijke onderscheid:
Dit beweert niet dat de mislukte agent is geïdentificeerd.
Het is een begrensde fallbackstrategie op crew-niveau.
Voor kleine stateless workflows kan dit acceptabel zijn. Voor productieworkflows met dure research, tools of neveneffecten, gebruik herstel op basis van checkpoints.
Hoe houd je het tokengebruik van CrewAI bij?
Gebruikstracking zou onderdeel moeten zijn van de routinglaag, niet een nakomertje.
Inspecteer aan het einde van de run het CrewAI-resultaat:
result, selected_models = run_with_fallback(topic)print("Selected models:")print(selected_models)print("Final result:")print(result.raw)print("Usage:")print(result.token_usage)
De exacte beschikbare gebruiksvelden kunnen afhangen van de CrewAI-versie en het uitvoeringstraject, dus behandel het geretourneerde resultaatobject als de bron van waarheid voor de versie die je deployt.
Een productieregistratie zou idealiter bevatten:
job_idagentmodelinput_tokensoutput_tokenstotal_tokenslatency_msfallback_usedfallback_reasonstatuscreated_at
Dit laat je vragen beantwoorden zoals:
Welke agent verbruikt het grootste deel van het budget?
Hoe vaak valt de analist terug?
Welk model heeft de hoogste latentie?
Hoeveel kost elke workflow?
Hoe beheer je kosten op agentniveau?
Multi-modelrouting is het meest nuttig wanneer het werkelijke werkbelastingverschillen weerspiegelt.
Bijvoorbeeld:
Researcher→ hoog volume→ goedkoper modelAnalyst→ laag volume→ sterker redeneermodelWriter→ gemiddeld volume→ algemeen productiemodel
Je kunt ook kosten beperken via agentconfiguratie.
Bijvoorbeeld:
max_iter=3
begrensd de iteratielus van de agent. Dit moet niet worden geïnterpreteerd als een harde limiet van precies drie API-calls of drie tokenbudgetten.
Aanvullende beheersmaatregelen zijn onder meer:
- taakcontext beperken
- tussenresultaten samenvatten
- herhaalbare research cachen
- maximale invoergrootte beperken
- maximale outputtokens beperken waar ondersteund
- tool-calls beperken
- per-gebruiker budgetten instellen
- per-workflow budgetten instellen
- fallbackfrequentie bijhouden
Hoe valideer je modellen vóór deployment?
Hardcode model-ID’s niet voor altijd.
Een model kan:
- niet beschikbaar worden
- worden hernoemd
- worden afgekeurd
- beperkingen krijgen
- in capaciteit veranderen
- in prijs veranderen
- incompatibel worden met een parameter die je applicatie gebruikt
CometAPI levert een modelcatalogus-endpoint dat programmatisch kan worden bevraagd, terwijl de publieke modeldirectory kan worden gebruikt voor menselijke modelontdekking.
Een deploymentcheck kan er als volgt uitzien:
curl -s \ https://api.cometapi.com/api/models \ -H "Authorization: Bearer $COMETAPI_KEY"
Valideer vervolgens dat je geconfigureerde model-ID’s bestaan vóór deployment.
Bijvoorbeeld, je CI-proces kan verifiëren:
gemini-3.7-flash → availableclaude-opus-5 → availablegpt-5.6 → available
Maak beschikbaarheidschecks niet tot een vervanging voor applicatietests. Dat een model in een catalogus staat, betekent niet dat elke parameter, tool of outputformat die door je CrewAI-agent wordt gebruikt, wordt ondersteund.
Hoe ziet het complete CrewAI-voorbeeld eruit?
Hier is een geconsolideerde implementatie:
import jsonimport osimport sysfrom collections.abc import Iteratorfrom dotenv import load_dotenvfrom openai import ( APIConnectionError, APIStatusError, APITimeoutError,)from crewai import Agent, Crew, LLM, Process, Taskload_dotenv()COMETAPI_KEY = os.environ["COMETAPI_KEY"]COMETAPI_BASE_URL = os.getenv( "COMETAPI_BASE_URL", "https://api.cometapi.com/v1",)PRIMARY_MODELS = { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6",}FALLBACK_MODELS = { "researcher": "gpt-5.6", "analyst": "gpt-5.6", "writer": "gemini-3.7-flash",}def cometapi_llm(model_id: str) -> LLM: return LLM( model=model_id, base_url=COMETAPI_BASE_URL, api_key=COMETAPI_KEY, timeout=60.0, max_retries=0, )def build_crew(model_map: dict[str, str]) -> Crew: researcher = Agent( role="Market Researcher", goal="Collect the facts needed to answer the topic", backstory=( "You create concise, source-aware research briefs " "and distinguish facts from assumptions." ), llm=cometapi_llm(model_map["researcher"]), max_iter=3, allow_delegation=False, ) analyst = Agent( role="Product Analyst", goal="Turn research into a defensible recommendation", backstory=( "You evaluate evidence, assumptions, risks, " "and trade-offs." ), llm=cometapi_llm(model_map["analyst"]), max_iter=3, allow_delegation=False, ) writer = Agent( role="Technical Writer", goal="Produce a concise technical decision memo", backstory=( "You write clear technical explanations " "without unnecessary hype." ), llm=cometapi_llm(model_map["writer"]), max_iter=3, allow_delegation=False, ) research_task = Task( description=( "Research this topic: {topic}. " "Return the key facts, uncertainties, " "and relevant sources." ), expected_output=( "A concise research brief with facts " "and open questions." ), agent=researcher, ) analysis_task = Task( description=( "Using the research brief, analyze {topic}. " "Identify the strongest conclusion and " "explain the major trade-offs." ), expected_output=( "A decision outline with evidence, " "assumptions, risks, and trade-offs." ), agent=analyst, context=[research_task], ) writing_task = Task( description=( "Write a concise technical decision memo " "about {topic}. State the recommendation early " "and preserve important caveats." ), expected_output=( "A polished technical decision memo in Markdown." ), agent=writer, context=[ research_task, analysis_task, ], ) return Crew( agents=[ researcher, analyst, writer, ], tasks=[ research_task, analysis_task, writing_task, ], process=Process.sequential, verbose=True, )def exception_chain( error: BaseException,) -> Iterator[BaseException]: current = error seen: set[int] = set() while current is not None and id(current) not in seen: seen.add(id(current)) yield current current = ( current.__cause__ or current.__context__ )def should_fallback(error: BaseException) -> bool: for current in exception_chain(error): if isinstance( current, ( APIConnectionError, APITimeoutError, ), ): return True if isinstance(current, APIStatusError): return ( current.status_code in {408, 429} or current.status_code >= 500 ) return Falsedef run_with_fallback(topic: str): routes = [ PRIMARY_MODELS, { **PRIMARY_MODELS, "writer": FALLBACK_MODELS["writer"], }, { **PRIMARY_MODELS, "analyst": FALLBACK_MODELS["analyst"], "writer": FALLBACK_MODELS["writer"], }, ] last_error = None for attempt, model_map in enumerate( routes, start=1, ): try: crew = build_crew(model_map) result = crew.kickoff( inputs={ "topic": topic, } ) return result, model_map except Exception as error: last_error = error if not should_fallback(error): raise if attempt == len(routes): raise print( f"Transient failure on attempt " f"{attempt}; trying fallback.", file=sys.stderr, ) raise RuntimeError( "No model route completed the crew." ) from last_errordef main(): topic = ( sys.argv[1] if len(sys.argv) > 1 else ( "Should a small SaaS add " "AI-generated meeting summaries?" ) ) result, selected_models = ( run_with_fallback(topic) ) output = { "selected_models": selected_models, "raw": result.raw, "tasks_output": [ task.raw for task in result.tasks_output ], "token_usage": str( result.token_usage ), } print( json.dumps( output, indent=2, default=str, ) )if __name__ == "__main__": main()
De belangrijke verbetering ten opzichte van de oorspronkelijke versie is dat de code niet langer ten onrechte impliceert dat een uitzondering de exact mislukte agent identificeert.
Het is expliciet een begrensde fallback-implementatie op crew-niveau.
Combineer voor productie hetzelfde routingbeleid met CrewAI-checkpointing.
Hoe voer je de CrewAI-workflow uit?
Sla het bestand op als:
crewai_multi_model.py
Voer vervolgens uit:
python crewai_multi_model.py \ "Should a small SaaS add AI-generated meeting summaries?"
Een succesvolle respons bevat vergelijkbare informatie:
{ "selected_models": { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6" }, "raw": "<final decision memo>", "tasks_output": [ "<research output>", "<analysis output>", "<writing output>" ], "token_usage": "<usage information>"}
De exacte respons en gebruikswaarden hangen af van de input, het modelgedrag, de CrewAI-versie en het uitvoeringstraject.
Als een retrybare fout de fallback-route activeert, toont het object selected_models de route die voor die crew-uitvoering is gebruikt.
Hoe ontwerp je modelrouting voor productie?
Een routingbeleid voor productie moet meer overwegen dan modelkwaliteit.
Een nuttige beslisfunctie is:
Model Score =Quality+ Reliability+ Context Fit+ Tool Compatibility- Cost- Latency
Je kunt dit op verschillende niveaus implementeren.
Kosten-gebaseerde routing
Eenvoudige taak → voordelig modelComplexe taak → premium model
Latentie-gebaseerde routing
Interactief verzoek → snel modelAchtergrondworkflow → model met hogere kwaliteit
Betrouwbaarheids-gebaseerde routing
Primair model ↓tijdelijke storing ↓fallbackmodel
Taak-gebaseerde routing
Research → Model AAnalysis → Model BWriting → Model CCode → Model D
De laatste benadering is bijzonder natuurlijk voor CrewAI omdat het framework elke agent al een afzonderlijke rol geeft.
Hoe maak je fallback veilig?
Een robuust fallbacksysteem moet vier regels afdwingen.
Geen fallback bij authenticatiefouten
Als de API-sleutel ongeldig is:
401
zal van model wisselen het probleem niet oplossen.
Geen fallback bij ongeldige aanvragen
Als de aanvraag ongeldig is:
400422
corrigeer dan de aanvraag.
Nooit onbeperkt fallbacken
Stel een harde limiet in:
MAX_FALLBACK_ATTEMPTS = 2
Een fallbacksysteem zonder limiet kan een dure retry-lus worden.
Maak fallbackmodellen aanvraag-compatibel
Een fallbackmodel moet de functies ondersteunen die jouw agent vereist.
Als de primaire agent bijvoorbeeld een specifieke tool of gestructureerde-outputgedrag vereist, moet de fallback hetzelfde contract ondersteunen.
OpenAI-compatibel betekent niet functie-compatibel.
Wat zijn de meest voorkomende fouten bij CrewAI + CometAPI?
| Symptoom | Waarschijnlijke oorzaak | Oplossing |
|---|---|---|
| 401 Unauthorized | Ongeldige of ontbrekende API-key | Controleer COMETAPI_KEY; geen fallback |
| 400 Bad Request | Ongeldige aanvraagparameters | Corrigeer de aanvraag |
| 404 Model Not Found | Verouderde model-ID | Controleer de huidige modelcatalogus |
| 408 Timeout | Tijdelijke time-out | Retry binnen een begrensd beleid |
| 429 Rate Limited | Te veel verzoeken | Back-off en opnieuw proberen |
| 500–504 | Tijdelijke server/gatewaystoring | Gebruik begrensde fallback |
| Agent probeert steeds opnieuw | Verborgen SDK-retries | Beheer max_retries |
| Voltooide taken draaien opnieuw | Volledige crew-retry | Gebruik herstel op basis van checkpoints |
| Ander model gedraagt zich anders | Modelcapaciteiten verschillen | Test elk model afzonderlijk |
| Onverwachte CrewAI constructorfout | Versiemismatch | Pin en verifieer CrewAI-versie |
Hoe scheid je CrewAI-fouten van modelfouten?
Dit onderscheid is belangrijk bij het debuggen.
Configuratiefouten
Missende API-sleutelOngeldige model-IDOngeldige base URLNiet-ondersteunde parameter
Deze zouden snel moeten falen.
Provider/API-fouten
401403404429500503
Deze vereisen verschillende afhandeling afhankelijk van de status.
Applicatiefouten
Ongeldige agentoutputTool gaf ongeldige data terugOntbrekende taakcontextNeveneffect mislukt
Deze worden niet per se opgelost door van model te veranderen.
Een volwassen agentsysteem zou daarom aparte afhandeling moeten hebben voor:
configuratie ↓API-transport ↓modelexecutie ↓agentlogica ↓toolexecutie ↓applicatieneveneffecten
Dit is veel veiliger dan een generieke:
except Exception: use_fallback()
Hoe bescherm je externe neveneffecten?
Fallback wordt aanzienlijk complexer wanneer agents meer doen dan tekst genereren.
Stel bijvoorbeeld een agent die:
- een databaserecord aanmaakt
- een e-mail verstuurt
- een externe API aanroept
- een CRM bijwerkt
Als het model time-out terwijl de externe actie is geslaagd, kan het opnieuw uitvoeren van de hele crew de actie dupliceren.
Gebruik:
- idempotency-keys
- taakcheckpoints
- transactieranden
- uitvoerings-ID’s
- duurzame taakstatus
- expliciete bevestiging van neveneffecten
Bijvoorbeeld:
job_id = crew_run_123task_id = writer_456
Sla deze identifiers op bij externe bewerkingen zodat een retry kan bepalen of de operatie al heeft plaatsgevonden.
Hoe monitor je multi-model CrewAI-workflows?
Log minimaal:
workflow_idagentmodeltaskstart_timeend_timelatencystatusfallback_usedfallback_reasoninput_tokensoutput_tokenstotal_tokens
Log niet:
API-sleutelsprivé-referentiesvolledige gevoelige promptsprivégebruikersdatanieuwe, ongeredigeerde modeloutput
Monitor per model:
Betrouwbaarheid
succesratetime-out-ratio5xx-ratiofallbackratio
Performance
p50-latentiep95-latentiep99-latentie
Kosten
input-tokenoutput-tokenskosten per taakkosten per voltooide workflow
Kwaliteit
taaksuccesratiohuman evaluationgeldigheid gestructureerde outputtool-call succes
Dit verandert modelrouting van een hardcoded voorkeur in een observeerbaar engineeringssysteem.
Hoe kies je tussen directe provider-API’s en CometAPI?
De keuze hangt af van je architectuur.
| Architectuur | Inloggegevens | Model wisselen | Providerintegratie | Gecentraliseerde routing |
|---|---|---|---|---|
| Directe provider-API’s | Meerdere | Aangepast | Hoog | Nee |
| Eén provider | Eén | Beperkt | Laag | Beperkt |
| CrewAI + CometAPI | Eén CometAPI-referentie | Op model-ID basis | Lager | Ja |
Als je applicatie slechts één provider en zijn native mogelijkheden nodig heeft, kan een directe integratie prima zijn.
Als je CrewAI-applicatie modellen van meerdere providers nodig heeft en je één toegangslaag wilt, wordt CometAPI aantrekkelijker.
Het belangrijkste punt is dat CometAPI CrewAI niet vervangt.
In plaats daarvan:
CrewAIAgent-orchestratie ↓CometAPIModeltoegang ↓Meerdere modellen
Elke laag heeft een andere verantwoordelijkheid.
Hoe schaalt deze architectuur?
Zodra het routingbeleid is gescheiden van de agentdefinities, vereist het toevoegen van een ander model niet dat je de hele applicatie opnieuw opbouwt.
Bijvoorbeeld:
PRIMARY_MODELS = { "researcher": "gemini-3.7-flash", "analyst": "claude-opus-5", "writer": "gpt-5.6", "coder": "YOUR_CODE_MODEL",}
Dezelfde architectuur kan dan ondersteunen:
Research-agentAnalyse-agentCoding-agentReview-agentWriting-agentFact-checking-agent
Elke agent kan een ander model hebben, terwijl dezelfde CometAPI-toegangslaag wordt gedeeld.
De volgende stap is om routing dynamisch te maken.
In plaats van:
"analyst": "claude-opus-5"
zou je uiteindelijk kunnen gebruiken:
select_model( task="analysis", budget=budget, latency_target=latency_target,)
Het routingsysteem kan dan uit goedgekeurde modellen kiezen op basis van applicatievereisten.
Wat is de beste productie-architectuur voor CrewAI + CometAPI?
Voor een kleine workflow:
Gebruikersinvoer ↓CrewAI ↓CometAPI ↓Modellen
Voor productie:
┌───────────────┐ │ Model Catalog │ └───────┬───────┘ │ ▼User → CrewAI → Routing Policy → CometAPI │ │ │ │ │ ├── Gemini │ │ ├── Claude │ │ └── GPT │ │ │ ▼ │ Cost / Quality / │ Latency / Policy │ ▼ Checkpoints │ ▼ Usage Tracking
De belangrijkste productiecomponenten zijn:
- Model-allowlist
- Per-agent routing
- Begrensde retries
- Taakcheckpoints
- Gebruikstracking
- Kostenbeheersing
- Model-compatibiliteitstests
- Observability
- Idempotente neveneffecten
Die architectuur is aanzienlijk robuuster dan simpelweg een try/except rond crew.kickoff() plaatsen.
Eén CometAPI-sleutel, verschillende modellen, helderdere agentrollen
De meest nuttige manier om over CrewAI en CometAPI samen na te denken is als twee complementaire lagen.
CrewAI definieert wat de agents doen.
CometAPI definieert hoe die agents toegang krijgen tot modellen.
Die scheiding maakt het mogelijk om een snel model toe te wijzen aan een researchagent met hoog volume, een sterker redeneermodel aan een analyseagent, en een algemeen productiemodel aan de uiteindelijke schrijver, zonder aparte providerintegraties in de workflow te onderhouden.
De eenvoudigste implementatie gebruikt één CometAPI-sleutel en één OpenAI-compatibele base URL:
https://api.cometapi.com/v1
Voor productie, zet de architectuur een stap verder: houd modelrouting in configuratie, valideer modelbeschikbaarheid vóór deployment, gebruik begrensde fallback alleen voor tijdelijke storingen, checkpoint voltooide taken, en registreer model- en gebruiksmetadata voor elke run.
Dat geeft je een veel duurzamer patroon dan simpelweg CrewAI aan één LLM koppelen:
CrewAI orkestreert de agents. CometAPI centraliseert modeltoegang. Model-ID’s sturen de routing. Checkpoints beschermen voltooide werkzaamheden. Gebruikstracking beheerst de kosten.
Veelgestelde vragen
Kan CrewAI meerdere AI-modellen in dezelfde crew gebruiken?
Ja. Wijs een andere LLM-configuratie toe aan elke CrewAI-agent. Elke configuratie kan zijn eigen model specificeren terwijl dezelfde CometAPI API-sleutel en base URL worden gebruikt.
Kan CrewAI verbinden met een OpenAI-compatibele API?
Ja. De LLM-configuratie van CrewAI ondersteunt een aangepaste base_url en API-sleutel voor OpenAI-compatibele endpoints.
Met CometAPI is de base URL:
https://api.cometapi.com/v1
Heb ik aparte API-sleutels nodig voor GPT, Claude en Gemini?
Bij toegang tot deze modellen via CometAPI kan de applicatie de CometAPI-referentie en het endpoint gebruiken in plaats van aparte providerreferenties in elke CrewAI-agent te implementeren.
Betekent één API-sleutel dat de modellen identieke mogelijkheden hebben?
Nee. De API-interface kan worden verenigd terwijl de modelcapaciteiten verschillend blijven. Contextvensters, toolondersteuning, parameters, outputgedrag, latentie en prijsstelling kunnen per model variëren.
Moet ik de hele CrewAI-workflow opnieuw proberen wanneer één model faalt?
Alleen voor eenvoudige, stateless workflows. Een volledige crew-retry kan voltooide taken herhalen en de kosten verhogen. Voor productieworkflows: checkpoint voltooide taken en hervat vanaf het mislukte deel waar praktisch.
De huidige checkpointing-functionaliteit van CrewAI is ontworpen om de executiestaat te behouden en na fouten te hervatten.
Moet elke CrewAI-exceptie model-fallback activeren?
Nee. Authenticatie, ongeldige aanvragen, ongeldige model-ID’s en niet-ondersteunde parameters vereisen doorgaans configuratiewijzigingen en niet een ander model.
Fallback is beter gereserveerd voor begrensde tijdelijke storingen zoals time-outs, rate limits en tijdelijke 5xx-responses.
Hoe houd ik de kosten van elke CrewAI-agent bij?
Noteer de agentnaam, model-ID, tokengebruik, latentie, uitvoeringsstatus en fallbacks voor elke taak. Gebruik de resulterende data om de kosten per agent en per workflow te berekenen.
Kan ik dynamisch het model wijzigen dat aan een agent is toegewezen?
Ja. Bewaar model-ID’s in een routingconfiguratie in plaats van ze direct in agentdefinities te embedden. Je applicatie kan dan modellen kiezen op basis van kosten, latentie, taaktype of beschikbaarheid.
Is CometAPI een vervanging voor CrewAI?
Nee. Ze werken op verschillende lagen. CrewAI orkestreert agents en taken, terwijl CometAPI een uniforme modeltoegangslaag biedt.
Waar vind ik de huidige CometAPI-modellen?
Gebruik de CometAPI modeldirectory (https://www.cometapi.com/models/?utm_source=chatgpt.com) voor menselijke modelontdekking en de model-API voor programmatische validatie. De huidige quickstart-pagina van CometAPI vermeldt 500+ modellen in de categorieën tekst, afbeelding, video en audio.
Bronnen
- CometAPI Quick Start (https://www.cometapi.com/quickstart/?utm_source=chatgpt.com)
- CometAPI Model Directory (https://www.cometapi.com/models/?utm_source=chatgpt.com)
- CometAPI API Documentation (https://apidoc.cometapi.com/?utm_source=chatgpt.com)
- CometAPI Python SDK (https://pypi.org/project/cometapi/?utm_source=chatgpt.com)
- CrewAI Documentation (https://docs.crewai.com/?utm_source=chatgpt.com)
- CrewAI LLM Configuration (https://docs.crewai.com/?utm_source=chatgpt.com)
- CrewAI Checkpointing (https://docs.crewai.com/?utm_source=chatgpt.com)
